I am pleased to see this proposal come to review. It lifts some restrictions in the use of opaque types and, as such, fits very well with the direction of Swift. As I'm not a Rustacean, I can't say I have extensive experience with the corresponding feature in Rust, but based on my limited understanding I think it compares favorably. I have thought about this topic at some length and studied both the original pitch and this revision.
Looking at this with fresh eyes after some time (and having not re-examined my prior opinions in the pitch phase), I do have some thoughts about the detailed design which may have evolved since prior--
Syntax for optionals
I very much appreciate the rationale behind requiring the parens in spelling (some P)?. Indeed, it is unimpeachable that this is the clearest possible spelling. However, the following points (which I agree with--and I think would be generally agreed upon) give me pause:
...a user's first instinct might be to write some P? . This latter syntax is moderately less verbose, and is, in fact, unambiguous...
...since P? is never a correct constraint, it would be possible to (and in fact this proposal's implementation does) provide a "fix it" to the user which suggests that they change some P? to (some P)?.
True, the fix-it certainly minimizes the burden to users. However, I'd argue that whenever there's a spelling for something that's both intuitive and always unambiguous (a rarity), anything required on top of that surely has to be, by the same token, unnecessary ceremony.
I'm not sold on the argument that some has to bind less tightly than ? just because -> and & do: Swift already goes through contortions for operators such as try for user ergonomics. And indeed, we admit that users' intuition here doesn't require some to bind less tightly.
That said, it is easier to add a special rule than to take one away, so I would be content with leaving the rules as-is for now and circling back to this at a later time if our expectations are proved out that users will widely expect to be able to write some P? without parens.
Higher order functions
This idea of features being easier to add later than to take away leads me to the proposed syntax as it applies here:
Consider the function func f() -> (some P) -> () . The closure value produced by calling f has type (some P) -> () , meaning it takes an opaque result type as an argument. That argument has some concrete type, T , determined by the body of the closure. [Emphasis mine.]
This decision should be considered in the context of generalized some syntax, which we are likely to implement in the future.
I think it's important to spell out that consideration. It took me some time in another conversation (thanks to @ensan-hcl, as I recall) to appreciate the issue here:
The "generalized some syntax" which is mentioned specifically in Future Directions would have (some P) -> () as a shorthand for a generic constraint, equivalent to <T: P>(T) -> ()—that is, the caller of the closure would determine the concrete type.
However, in the case of the closure returned by f discussed above, (some P) -> () actually means (T) -> <T: P>() (to use the "fully generalized reverse generics" syntax also mentioned in Future Directions)—which is to say, the callee (i.e., the closure) determines the concrete type.
There has been some disagreement in that prior conversation about which of these scenarios should be endowed with the spelling of (some P) -> (), but for certain they cannot both be, since they mean very different things. For this reason, if this proposal were to be accepted as written allowing higher order functions declared func f() -> (some P) -> (), it would make the proposal's own future direction impossible due to ambiguity.
I don't think we have to resolve the disagreement here (although I happen to agree with the proposal's future direction). It would suffice to disallow such higher order functions with opaque types, just as the proposal suggests as an alternative, since it is difficult (usually impossible) to actually call the returned closure anyway and it would be of limited use. We could then resolve the question regarding "generalized some syntax" at a later time, and indeed we could still allow the use of higher order functions returning possibly uncallable closures at a later time when "fully generalized reverse generics" are made possible.
This course of action would be consistent with that line of thinking that it is easier to add features later than to remove them, allowing currently unsettled questions to be settled later rather than foreclosing them for the limited purpose of allowing higher order functions to return usually uncallable closures.