What's the effect of override keyword in protocol declaration?

Today I was walking around Swift repository and found an unseen expression: swift/BidirectionalCollection.swift at main · apple/swift · GitHub

public protocol BidirectionalCollection: Collection
where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
  // FIXME: Only needed for associated type inference.
  override associatedtype Element
  override associatedtype Index
  override associatedtype SubSequence
  override associatedtype Indices
...
  override func index(after i: Index) -> Index
//^^^^^^^^ `override` in protocol...?
...

My understanding was that override is explicitly for reference types and it was first time to see it in the other area.
I couldn't find any mention of it in The Swift Programming Language (Swift 5.6) neither.

Test code:

protocol RootProtocol {
    func helloWorld()
}

protocol OtherProtocol: RootProtocol {
    override func helloWorld()
}

extension RootProtocol {
    func helloWorld() {
        print("Hello World")
    }
}

extension OtherProtocol {
    func helloWorld() {
        print("Hello World from the Other Side")
    }
}

struct RootConcrete: RootProtocol {}
struct OtherConcrete: OtherProtocol {}

RootConcrete().helloWorld()
OtherConcrete().helloWorld()

This compiles with Swift 5.6.

Then, off course, output is below regardless it's marked as override or not:

Hello World
Hello World from the Other Side

So, what's the actual effect of this, and is this well-known / widely used technique?
Thanks.

The override keyword, when used with protocols, is an internal undocumented feature implemented for ABI-related reasons (namely, to drop the overriding member from witness tables) that has never gone through Swift Evolution:

https://github.com/apple/swift/pull/19034

It is not a part of the official language, which does not require any keyword for restating a protocol requirement.

A shadowing requirement for ABI purposes in a refining protocol is annotated with @_nonoverride, also an internal undocumented feature.

4 Likes

Ah... I see. That makes sense really and good to know.
Makes also perfect sense that it has been there for years.

Thanks for the input!

edit: Also thanks much for the specific PR :pray:

override on associated-type declarations has (or at least had, not sure of the current situation) some effect on type inference. I can’t remember the details, but in some situations omitting the override keyword would cause type inference to fail.

Well, my initial thought was, in case if it was for internal use (which is now I know it is), it's a bit scary because it's not underscored, normal reserved keyword you would often see if you work with Obj-C modules which is apparently not a rare-case.

Although at the same time I think there will be (almost) no case that one uses it accidentally, causing an unintended behavior... I did not happen to even think to type override in protocol until today.

It does not directly affect associated type inference. The bug with associated type inference is that associated types must be re-stated in an inherited protocol for inference to work. We didn't want such associated types to be part of the ABI, since we'd like to fix the bug and remove them at some point, so we implemented override checking for protocol requirements.

The standard library is built with a special frontend flag (-warn-protocol-override) where a missing override keyword on a re-stated protocol requirement is a warning. Normally this is not diagnosed since users don't generally care if a protocol requirement is re-stated or not.

4 Likes