SE-0503: Suppressed Default Conformances on Associated Types With Defaults

Hi Swift community,

The review of SE-0503: Suppressed Default Conformances on Associated Types With Defaults begins now and runs through January 25th, 2026.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager. When emailing the review manager directly, please keep the proposal link at the top of the message.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/main/process.md

Thank you,

Ben Cohen
Review Manager

11 Likes

I find the "default constraint sets" alternative particularly compelling because of future evolution. It would mean there wouldn't have to be an entirely new Collection hierarchy for noncopyable types. It would also mean that, after a new Collection hierarchy is introduced, adding a new suppressible protocol like ~Runcible wouldn't necessitate a third Collection hierarchy.

The proposal states about the "protocol-defined default requirements" alternative:

This might also serve as a way for a protocol to opt generic parameters out of defaulting to Copyable and/or Escapable when the protocol is used as a constraint, which may be desirable for protocols that are only used with noncopyable or nonescapable conformers in practice.

Even if "protocol-defined default requirements" are not adopted, I think that specific functionality would be especially helpful if an ExclusiveCopyable protocol that sits between Copyable and ~Copyable is ever introduced. Then it would be possible to make T: ExclusiveCopyable sufficient instead of making people write T: ExclusiveCopyable & ~Copyable & ~Escapable.

I am in strong favour of allowing suppressed conformances on associated types.

On the other hand, changing an associated type declaration in an library to suppress conformance is can be an ABI-breaking change. For example, an extension of a protocol providing a default implementation could have its symbol name change, as these two implementations of greet must have distinct names:

Can this clause be clarified? Under what conditions is it safe to change an existing associated type declaration (and conversely, what would make them unsafe?) What steps would need to be taken to ensure a safe transition? I ask because there are a couple of protocols in Swift Testing that would benefit from a change here.

1 Like

I believe the example to illustrate the rationale in the "Default Witness" section is incorrect.

func runForwardsInt(_ it: some Iterable<Int>) {
  _ = copy it.getIter()
}

I think this should always be an error. Because Iter is not a primary associated type of Iterable, some Iterable<Int> should be desugared only into T where T: Iterable, T. Element == Int /*, T.Iter: ~Copyable */. Given the above constraints, it does not matter if its default Iter implementation is Copyable or not.

This proposal would make it safe to suppress a primary associated type's conformances, but not non-primary associated types.

The problem here is subtle. The issue is that old code from before the conformance was suppressed may have relied on that now-suppressed capabilities.

  1. Declare protocol P { associatedtype A } in an ABI-stable library. No primary associated type.
  2. Someone writes public func f(_ arg: some P) in another ABI-stable library.
  3. The body of f makes a copy of an A, which is allowed.
  4. P is updated to protocol P { associatedtype A: ~Copyable }.
  5. Declare struct S { typealias A = NoncopyableType }
  6. Pass an instance of S to f
  7. f tries to call an unavailable copying value witness function of Noncopyable

Note the author of P has no control over f. There is no circumstance where P can "check" if there are functions like f out there.

As the proposal describes, this is fine for primary associated types because you must explicitly suppress ~Copyable in your function declaration, and that makes a new symbol. Previously compiled functions can't yet be used with types with non-copyable primary associated types. (This is also why it's fine to declare protocols themselves retrospectively ~Copyable). The problem is only when you want to retroactively suppress conformances on non-primary associated type. You just can't, in an ABI-stable way.

There is a hazard here. It becomes tempting to declare an associated type primary purely so that it can be retrospectively changed to suppress copyability. Library authors are going to need to decide whether that makes sense for their library or not, and avoid the temptation to mark an associated type that really isn't really "primary" to the protocol, just to allow this.

2 Likes

Review Conclusion

The proposal has been accepted.

2 Likes