That’s not how constrained existentials were designed, though. There is missing logic in the type checker for this, but today what you write should be diagnosed as a conflict. In general, the generic arguments don’t influence the existential generic signature in any way; it’s a property of the existential type’s generalization only.
It didn’t occur to me that defaulting interacts badly with existentials; this is an argument against this pitch, but maybe a weak one.
(I still think the original version of the pitch without any sort of “defaulting” behavior for associated types was the best one, and the least inconsistent. Associated types are quite unlike generic parameters.)
This is only one side of the story, though. Consider the scenario when, as you propose, we don't default Allocator to Copyable: In that case, inside extension Queue { ... }, the author will have to contend with writing code that uses an (implicitly) ~Copyable allocator potentially before they're ready to learn about noncopyability. Either way, there is a paper cut here.
Sure, writing protocol extension methods is a step more "advanced" than just calling methods on concrete types. But a method being unavailable because some condition isn't satisfied is much less "unprogressive": developers encounter similar diagnostics when they inadvertently try to invoke internal APIs or methods unavailable for some platform all the time. By contrast, consider the case where an everyday app developer relies on a dependency that generalizes some protocol for noncopyable types (tagging a new semver major). The developer sets up a new project, pulling in the latest version of that dependency—after all, it's a new project!—after reviewing the changelog which doesn't mention any features being removed. They get to work, only to find that the same useful extension they've copied from project to project that worked yesterday now throws up errors because an associated type is now implicitly noncopyable. That's got to be very frustrating if they're not ready to handle noncopyable types.
Essentially, I don't think we have a "progressive disclosure story" for this: there is an inevitable bump in the rug and we're pushing it around rather than flattening it out. I'm not convinced that you've demonstrated why defaulting all associated types is not a superior solution here.
One author-side option that we could potentially entertain is a sort of ad-hoc spelling like associatedtype Element: ~Copyable = some Copyable to spell out that defaulting to a Copyable type is intended. But any design that surfaces a customizable default like that would render it impossible for a user who hasn't progressed to learning about noncopyable types to rely on anything about how their extensions will behave, since knowing what any extension Queue means would require consulting the original protocol declaration and understanding how suppressed conformances work.
A language cannot be designed to shield against every possible source break that a library author can dream up in their next major version bump. They could have deleted a method requirement that someone’s favorite copy-pasted extension relied on. They could even delete the whole protocol.
Luckily, your hypothetical scenario has an easy fix… write where Thing: Copyable on the extension. The compiler would’ve told them that it’s not Copyable within the extension to guide them to that solution. I don’t think it’s a stretch of the imagination to think that someone who can understand protocol extensions could write a where-clause that utters the protocolCopyable.
The extensions would use the set of defaults that the library author thinks will make the most sense for their users. The expectation is that they choose the right set of defaults for the common or expected type of conformer, so as to minimize the noise in the where clause. If the library author got it wrong, then people will indeed need to consult the protocol, unless if the compiler can provide useful diagnostics.
Library authors are already in charge of choosing the right assumptions for associated types. For example, if someone published this protocol,
public protocol Set {
associatedtype Element : Equatable
// ...
}
they’re making the assumption that users can get by without Element being Hashable. That means if users choose to conform to this Set, and it’s actually backed by a hash-table, they need to write extensions where Element: Hashable to provide extra functionality for themselves (like a faster containment check). If everyone has to do that to make good use of the protocol, then the library author made the wrong assumption about their users.
I have yet to see a convincing example where someone wants all of their suppressed associated types to be assumed to be Copyable and Escapable. Given that one of those must exist, is that truly the right behavior for all protocols ? I’ve provided one plausible example where it isn’t right.
My point is that the progressive disclosure argument which you bring up would argue for defaulting either everything or, if not feasible, as much as possible to be copyable and escapable. By that metric—which is not the only metric, but which you invoked as a justification for the currently pitched design and which we’ve (rightly, IMO) prioritized for noncopyable types—every associated type which doesn’t get defaulting behavior is an instance where we fall short. It becomes particularly mystifying to users if we end up in a “uncanny valley” where the rules encourage a simplified mental model that works 99% of the time but then causes inscrutable errors 1% of the time. The progressive disclosure argument doesn’t fall down because we can find examples—even many—where the defaulting behavior is not desirable, since it’s not about what’s best for expressivity but what’s best for progressive learning and teaching.
If, on the other hand, you want behavior to be entirely in the hands of the protocol author as you now argue, prioritizing authorial intent over language-level progressive disclosure, that is a reasonable approach but a totally different one. It occasions implementation complexity for both the language and its users in exchange for that expressivity, but as you show, it allows for bespoke rules that fit defaulting to particular protocol semantics.
But that argument doesn’t carry the day, to my mind at least, for some compromise heuristic like “primary associated types only get defaults,” which is necessarily both inflexible (working against your point above) and also incomplete (working against your point about progressive disclosure).
(That said, it would appear as I’ve said above that your example where the overwhelming majority of uses are expected to default to some noncopyable associated type would be addressed by a very targeted rule that associatedtype T = U doesn’t get defaulted to T: Copyable if U is not copyable. This may not be so nice to implement though.)
As one of the SE-0346 authors, my perspective is that the key tentpole source compatibility guarantee of SE-0346 is the ability to adopt primary associated types in protocols that predate SE-0346. This was necessary for adopting primary associated types across the library ecosystem after SE-0346 was implemented. That's not quite the same as it being generally important for a new protocol to be able to add primary associated types later in a source compatible way, which I personally don't think is a critical capability of primary associated types. I think that protocols that are added to libraries in today's Swift should consider primary associated types as part of the original design.
EDIT: I didn't read the entire thread before posting this, I've effectively repeated what Slava said upthread
Fully agree. I don’t buy @xwu argument on this. This feature has been part of the language for long enough for actively maintained libraries to consider it. The proposed change is not going to happen overnight. It gives the lagging library authors another nudge to review their design for potential primary associated types, within the original design intent. If those library authors have concerns, they should raise their specific and concrete concerns. This may include standard and core libraries authors/maintainers, as well.
P.S.: I did see @Slava_Pestov ’s post up thread, but was too busy/lazy to respond at the time or seek to find the specific post later. Gosh I’m getting old! On the bright side, at last I managed to update the 20 years old Gravatar image for my profile.