Function which takes an Iterator<Item = Box<dyn Any>>

Finally the package built properly :hot_face:, so there is documentation on my project on docs.rs available :smiley:.

Consider the method mmtkvdb::Env::open_dbs (source code available behind the link) which opens several databases:

unsafe fn open_dbs<'a, K, V, C>(
    &self,
    metas: impl IntoIterator<
        IntoIter = impl Iterator<Item = &'a DbOptions<K, V, C, Option<CString>>> + ExactSizeIterator
    >
) -> Result<Vec<Db<K, V, C>>, Error> where
    K: ?Sized + Storable,
    V: ?Sized + Storable,
    C: Constraint;

Each database may use different types for their keys and values. Thus, the DbOptions builder uses the typestate pattern and has type arguments K and V for the key and value type.

The open_dbs method opens several databases at once (it will have to acquire a mutex for it and do a few other things, so when multiple databases are opened, it may make sense to only do that once, which is why I allow passing multiple DbOptions through an iterator). However, while the signature of open_dbs is generic over different K and V types, it does not support opening databases with different keys (or values) in one call, because K and V are particular types for each invocation of open_dbs.

To overcome the limitation of only being able to open multiple databases with the same key (and value) types, I wanted to use dyn objects. The caller of open_dbs could then downcast each element in the result according to the (known) types K and V.

In practice, the code quickly gets very complex though. I might just leave the interface as is and accept the overhead of opening differently-typed databases in multiple calls.

I wonder, however, if similar problems occurred in other contexts where there are lists of structs with type arguments passed to a function that returns a list of different structs with the same type arguments (in my example above: K, V, C appear both in the arguments as well as in the result of the function).

1 Like