Swift protocol with “where Self” clause

The ability to put superclass constraints on protocols declarations (that is, being able to define protocol P where Self : C where C is the type of a class) was a premature consequence of
SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x can cause miscompilation and crashes, so I would avoid using it until Swift 5.

In Swift 5 (Xcode 10.2) the feature has now been implemented. From the release notes:

Protocols can now constrain their conforming types to those that
subclass a given class. Two equivalent forms are supported:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 

Swift 4.2 accepted the second form, but it wasn’t fully implemented
and could sometimes crash at compile time or runtime. (SR-5581)
(38077232)

This syntax places a superclass constraint on MyView which restricts conforming types to those inheriting from (or being) UIView. In addition, the usage of MyView is semantically equivalent to a class existential (e.g UIView & MyView) in that you can access both members of the class and requirements of the protocol on the value.

For example, expanding upon the release notes’ example:

protocol MyView : UIView {
  var foo: Int { get }
}

class C : MyView {} // error: 'P' requires that 'C' inherit from 'UIView'

class CustomView : UIView, MyView {
  var foo: Int = 0
}

// ...

let myView: MyView = CustomView(frame: .zero)

// We can access both `UIView` members on a `MyView` value
print(myView.backgroundColor as Any)

// ... and `MyView` members as usual.
print(myView.foo)

Leave a Comment