Implicit generics

Metaprogramming like frunk does is sort of a special case; most code won't use extra type inference variables the way that frunk does. But also, at least in theory, the example signature there could also be written as

fn print_height<'a, A>(obj: &'a A) -> String
where
    &'a A: PathTraverser<Path!(dimensions.height), impl Sized, TargetValue = &'a usize>
        + PathTraverser<Path!(dimensions.unit), impl Sized, TargetValue = &'a SizeUnit>,

except that impl Trait isn't permitted in this position because it's very unclear whether this is a "universal" type variable (chosen by the caller, implementation must work for any possible choice) or an "existential" type variable (chosen by the implementation, caller must work for any[1] possible choice).

The more specific case of your example

fn foo(foo: impl Foo<impl Sized>)

which is "nested impl Trait" rather than "impl Trait in bounds" might be made permissable in the future, since it's less unclear which direction the impl will make opaque, but that's still a good ways off. IIRC, a main question is handling impl Fn() -> impl Trait, as it isn't clear how return position inside argument position impl trait ("RPIAPIT" :upside_down_face:) should behave[1:1], and to the type system that's just an associated type equality bound (i.e. impl Fn<(), Output=impl Trait>).

There's also a different thread currently open about using _ as a kind of minimally bound type hole in a signature, which could be somewhat related to the desire here.


  1. The answer is probably that it should be an associated type trait bound (e.g. perhaps impl Fn<(), Output: Trait>) rather than an equality bound, but defining a composable definition of why that's the desugar is far from straightforward. ↩︎ ↩︎

3 Likes