On Thu, Apr 06, 2023 at 02:02:55PM +0900, Asahi Lina wrote: > On 05/04/2023 23.44, Daniel Vetter wrote: > > On Tue, Mar 07, 2023 at 11:25:43PM +0900, Asahi Lina wrote: > > > +/// Look up a GEM object handle for a `File` and return an `ObjectRef` for it. > > > +pub(crate) fn lookup_handle(file: &DrmFile, handle: u32) -> Result<ObjectRef> { > > > + Ok(ObjectRef::new(shmem::Object::lookup_handle(file, handle)?)) > > > +} > > > > So maybe my expectations for rust typing is a bit too much, but I kinda > > expected this to be fully generic: > > > > - trait Driver (drm_driver) knows the driver's object type > > - a generic create_handle function could ensure that for drm_file (which > > is always for a specific drm_device and hence Driver) can ensure at the > > type level that you only put the right objects into the drm_file > > - a generic lookup_handle function on the drm_file knows the Driver trait > > and so can give you back the right type right away. > > > > Why the wrapping, what do I miss? > > Sigh, so this is one of the many ways I'm trying to work around the "Rust > doesn't do subclasses" problem (so we can figure out what the best one is > ^^). > > The generic shmem::Object::lookup_handle() call *is* fully generic and will > get you back a driver-specific object. But since Rust doesn't do > subclassing, what you get back isn't a driver-specific type T, but rather a > (reference to a) shmem::Object<T>. T represents the inner driver-specific > data/functionality (only), and the outer shmem::Object<T> includes the > actual drm_gem_shmem_object plus a T. This is backwards from C, where you > expect the opposite situation where T contains a shmem object, but that just > doesn't work with Rust because there's no way to build a safe API around > that model as far as I know. Ah I think I just got confused. I did untangle (I think at least) the Object<T> trick, I guess the only thing that confused me here is why this is in the shmem module? Or is that the rust problem again? I'd kinda have expected that we'd have a gem::Object<T> here that the lookup_handle function returns. So for the shmem case I guess that would then be gem::Object<shmem::Object<T>> for the driver type T with driver specific stuff? I guess not very pretty ... > Now the problem is from the higher layers I want object operations that > interact with the shmem::Object<T> (that is, they call generic GEM functions > on the object). Options so far: > > 1. Add an outer wrapper and put that functionality there. > 2. Just have the functions on T as helpers, so you need to call T::foo(obj) > instead of obj.foo(). > 3. Use the undocumented method receiver trait thing to make shmem::Object<T> > a valid `self` type, plus add auto-Deref to shmem::Object. Then obj.foo() > works. > > #1 is what I use here. #2 is how the driver-specific File ioctl callbacks > are implemented, and also sched::Job<T>. #3 is used for fence callbacks > (FenceObject<T>). None of them are great, and I'd love to hear what people > think of the various options... > > There are other unexplored options, like in this GEM case it could be > covered with a driver-internal auxiliary trait impl'd on shmem::Object<T> > buuut that doesn't work when you actually need callbacks on T itself to > circle back to shmem::Object<T>, as is the case with File/Job/FenceObject. Ok I think I'm completely lost here. But I also havent' looked at how this is all really used in the driver, it's really just the shmem:: module in the lookup_handle function which looked strange to me. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation hvettp://blog.ffwll.ch