3 ms·
Thinking about this problem again kinda nerd-sniped me, so sharing a brain-dump here. The first one: any type that fulfills the trait bounds set by the definer
by GolDDranks 6y ago
Thinking about this problem again kinda nerd-sniped me, so sharing a brain-dump here.
The first one: any type that fulfills the trait bounds set by the definer of the trait, makes sense here. If we want all associated types of ! uniformly to map a single type, the only possible choice would be !, because we are trying to define it here so that it fullfills all possible trait bounds. Another choice would be the "top" type: a generic T (module the trait bounds). Here, the type inference would give up, as it would have no information about the type, and user of the trait would need to fill in whatever type they desire in this specific type-level expression. Any other type would be kinda arbitrary, and not maximally expressive in either way.
That the user would need to select a type, is an interesting choice in the sense, that <! as Foo> would not be a valid expression in that case. It would need to be something like <! as Foo<AssocType=MyType>>, which is intriguing to me: the user of the trait would become basically an implementor of it, and passing ! to anywhere with a bounded generic type T: Foo, would instantiate
not only the type T with !, but also the trait Foo with <AssocType=MyType>!
The second and the third ones: these are even tougher, as they are expressions that produce values. Rust doesn't guarantee that someone who has a type can produce a value of that type just by the virtue of having the type. But mimicking the first case, one could either imagine that they are panicking expressions of type !, which, confortably is a subtype any type, and thus any associated expression! But panicking in such cases sounds a bit awful from resiliency perspective. Another one is that again, like with the second case, the user would instantiate the trait Foo itself with <ASSOC_CONST=CONST> or <assoc_fn=func>. This would be also maximally flexible.
However, instantiating traits by setting their "parameters" is not something that Rust currently has. To be able to do that in generic code, one must also have a way to propagate such instantiated traits (e.g. from output to input). One could maybe do this without introducing "trait variables" or anything like that, by just tracking where type variables go. Still, it's a whole new consept in the already complex and hard to understand trait system.