Correct; since there's no optional on the right hand side of that typealias, its meaning is unchanged by this proposal.
On the surface, this seems like a reasonable change. I have mixed thoughts on it though from subtle language grammar and implementation points of view, though.
In Swift expressions, postfix operators always bind more closely than prefix operators—that's a fundamental parsing rule in the language. Now, types don't always have to follow the same rules as expressions with regard to "operators" when they're parsed in type contexts, but there's one rub: types that must be parsed in expression context and be converted later during semantic pre-checking. Something like:
let x = [() -> ~Copyable?]()
that must produce a parse tree like (~(Copyable?)) because we have no way of knowing at parse time whether that's a type or some other expression.
On the other hand, if we see any in that context, the parser knows that what follows must be a type, so it can enter a type parsing context. In other words,
let x = [() -> any ~Copyable?]()
could use different type parsing rules that fold the ~ into the constraint.
Now here's where things get more interesting: unlike existentials of regular protocol constraints, existentials of suppressed constraints unconditionally emit a warning:
let x = [() -> P?]() // OK
let x = [() -> (~Copyable)?]()
// `- warning: constraint that suppresses conformance requires 'any';
// this will be an error in a future Swift language mode [#ExistentialAny]
If we were already at the point where any was required, I'd say we could go for it and handle ~ here. But to do that today where the any-less form is still allowed would require some concession:
- We subsume
~ in type contexts but not in expression contexts, leaving the current surface language in an inconsistent state
- We subsume
~ in all contexts, which requires special casing the expression form during semantic pre-checking
- However, my original implementation did this (avoided changing the parse trees anywhere and did the rearrangement during pre-checking) and it was felt to be the wrong approach to take. Unlike the existing support for just
? which could be handled entirely on the parse tree side, supporting ~ would force us into a position where we have to use the non-preferred implementation to handle a subset of valid syntax.
I would need to double-check this. One thing I'd like clarity on is, is it permitted for a .swiftinterface from a newer compiler to be consumed by an older compiler if the interface doesn't use any language features newer than the compiler that consumes it? If so, using the new syntax wouldn't be safe. If that use case isn't supported, then I think we should use the more compact syntax whenever printing an AST.