Naming the unnameable


I think it is important to think about the complete picture of how we want existential types to work. impl Trait in return is on stable as wel as the controversial impl Trait in argument position. The existential type rfc was accepted however the precice syntax remains an unresolved question.

Personally I think that existential types should use the same notation as impl Trait this way

type Name = impl Trait;

would be an existential type with name Name. The presice type would be infered similar to how let is infered today. There should always be a way to create the Name and from that we can infer the type. This would extend the way impl Trait currently works in a way that feels intuitive to me. It also has no need for more syntax to extend the already present template <T> syntax and the impl Trait syntax.

That is my opinion however I just want to start the discussion. I think that naming unable types is an important issue currently and I want to solve it in an coherent way that fitst in well with the rest of the language. If you feel like there is a case that is not solved by existential types this would be the place to bring it up.


I would heavily support this syntax, if there aren’t any parsing problems with it, because:

  • existential is a huge keyword
  • It’s often possible to understand an idea before understanding the type theory that underpins it. I feel like you can look at type Name = impl Trait;, having a basic understanding of how impl Trait works, and understand kind of what’s going on. Having an extra word like existential in there is going to turn a lot of beginners away when they’re perfectly able of understanding the idea


I think a good step would be stabilizing the Fn family of traits. Once implementing Fn traits for a struct becomes possible, one would have the option of returning such a struct from a function, allowing returning named ‘closures’. Of course this would be much more verbose than using -> impl Fn. Once we get at this point it might be worth investigating whether it would make sense to add sugar that does this automatically somehow.


Another option would be to have the foo as the name of the type of the function fn foo() { /*..*/ }.


I really don’t think we should be doing another bikeshed thread about existential type syntax. There are already literally hundreds of comments about this on the original RFC thread and literally hundreds more on the tracking issue with no sign of a consensus. I ran out of things to say on the subject ages ago and I was only around for about half of the first of those threads.

In fact, back when I was in that first thread it seemed “obvious” that type Name = impl Trait; had conclusively won. I honestly have no idea why [keyword] type Name: Trait; is still considered a serious contender.

So the most constructive thing I can say is that we should probably do what this guy suggests:

Perhaps we’re reaching the point that our one-liners on their own can’t really bridge this consensus gap between type Inferred: Trait and type Inferred = impl Trait.

Do you think it would be worth putting together an experimental implementation of this feature with any syntax (even the one specified in the RFC) so we can start playing with it in larger programs to see how it fits in context?