> > > +pub struct MemoryRegionOps<T>( > > > + bindings::MemoryRegionOps, > > > + // Note: quite often you'll see PhantomData<fn(&T)> mentioned when > > > discussing > > > + // covariance and contravariance; you don't need any of those to > > > understand > > > + // this usage of PhantomData. Quite simply, MemoryRegionOps<T> > > > *logically* > > > + // holds callbacks that take an argument of type &T, except the type > > > is erased > > > + // before the callback is stored in the bindings::MemoryRegionOps > > > field. > > > + // The argument of PhantomData is a function pointer in order to > > > represent > > > + // that relationship; while that will also provide desirable and > > > safe variance > > > + // for T, variance is not the point but just a consequence. > > > + PhantomData<fn(&T)>, > > > +); > > > > Wow, it can be wrapped like this! > > I like your enthusiasm but I'm not sure what you refer to. ;) Maybe > it's worth documenting this pattern, so please tell me more (after > your holidays).
Throughout the entire holiday, I couldn't think of a better way to express this. I find it particularly useful when wrapping multiple callbacks. In the future, I want to explore more use cases where this pattern can be applied. > > > +impl MemoryRegion { > > > + // inline to ensure that it is not included in tests, which only > > > + // link to hwcore and qom. FIXME: inlining is actually the opposite > > > + // of what we want, since this is the type-erased version of the > > > + // init_io function below. Look into splitting the qemu_api crate. > > > > Ah, I didn't understand the issue described in this comment. Why would > > inlining affect the linking of tests? > > If you don't inline it, do_init_io will always be linked into the > tests because it is a non-generic function. The tests then fail to > link, because memory_region_init_io is undefined. I find even if I drop the `inline` attribution, the test.rs can still be compiled (by `make check`), I think it's because test.rs hasn't involved memory related tests so that do_init_io isn't linked into test.rs. > This is ugly because do_init_io exists *exactly* to extract the part > that is not generic. (See > https://users.rust-lang.org/t/soft-question-significantly-improve-rust-compile-time-via-minimizing-generics/103632/8 > for an example of this; I think there's even a procedural macro crate > that does that for you, but I can't find it right now). Thanks! I see. I agree to keep `inline` anyway.