Method override with a generic signature with requirements not imposed by the base method

The reason I made this change is because previously the compiler was allowing unsound code to compile, which later led to runtime crashes. Yes, sometimes the code would work, but that doesn't mean the code was safe.

Here's an example (based on the code you posted):

public protocol P {}
public protocol Q {}
public protocol R {
  func r()
}

open class A {
  open func foo<T: P & Q>(arg: T) {}
}

open class B: A {
  open override func foo<T: P & Q & R>(arg: T) {
    arg.r() // oops... this will actually crash in <= 5.1
  }
}

class C: P, Q {}

let a: A = B()
a.foo(arg: C())

You can see what the problem is - C does not conform to R (just P and Q) but we managed to pass it to B.foo (via A). So, calling R's requirement (the function r()) on it is illegal inside B.foo and thus leads to a crash.

And if possible any workarounds

You probably need to change your code.

I've tried searching for the reference numbers in the Release notes but can't find anything.

The main ticket is SR-4206 and the PR is https://github.com/apple/swift/pull/24484

2 Likes