override
is implied by having the same requirement stated in a more-refined protocol as in a protocol it inherits from. It is allowed to be stated explicitly primarily to suppress the warning produced by -warn-implicit-overrides
.
What you surmise is correct. When a protocol requirement "overrides" one from an inherited protocol, this requirement always gets the same witness as that of the inherited protocol. At the implementation level, there is no new entry for an override
requirement in the witness table.
This is correct.
@_nonoverride
says that the restated requirement does not have to have the same witness in a more-refined protocol as in the protocol it inherits that originally stated the requirement. In the implementation, this means that a @_nonoverride
requirement introduces a new entry in the witness table. If you look at where @_nonoverride
is used in the Standard Library, they are for cases where the semantics or complexity of operations (like distance(from:to:)
) change in the protocol inheritance hierarchy: distance(from:to:)
on a Collection
is forward-only, on a BidirectionalCollection
can go backwards, and on a RandomAccessCollection
is
@_nonoverride
is very, very important when dealing with conditional conformances, because it gives you more-capable witnesses in your conformances to protocols like BidirectionalCollection
. Without it, for example, a wrapper around a Collection
that had a conditional conformance to BidirectionalCollection
would not be able to provide a more-specialized implementation of the wrapper semantics for bidirectional collections.
Note how this is the same problem we've been discussing, where we really want to be able to pick a more-specialized witness when we have a more capable type. The override
/ @_nonoverride
dance was an implementation band-aid to get conditional conformances in the standard library to provide (mostly) the right behavior, using an ABI we could live with.
Doug