Reputation: 1697
I just updated to Xcode 11.4. I'm receiving the following error:
Overridden method 'equals' has generic signature <T where T : Gradient> which is incompatible with base method's generic signature <T where T : Fill>; expected generic signature to be <T where T : Fill>
class Fill: Equatable {
func equals<T>(other: T) -> Bool where T: Fill { }
}
func ==<T> (lhs: T, rhs: T) -> Bool where T: Fill {
return lhs.equals(other: rhs)
}
class Gradient: Fill {
override func equals<T>(other: T) -> Bool where T: Gradient { }
}
How this changed?
Upvotes: 1
Views: 980
Reputation: 719
The reason why you cannot change constraints like that is because doing so would violate Liskov substitution principle. The compiler has never checked the generic signature of overridden functions and this led to various runtime crashes, so I implemented this error in the Swift 5.2 compiler.
Let's take a look at your own example to understand what's wrong. One can write the following code:
let fill1: Fill = Fill()
let fill2: Fill = Gradient()
let isEqual = fill2.equals(other: fill1)
This is not correct, because Gradient.equals(other:)
requires other
to inherit from Gradient
. However, because fill2
has a static type of Fill
, I am able to bypass that constraint and pass a value of type Fill
instead.
If Gradient.equals(other:)
tries to access a property or a function on other
which only exists on an instance of Gradient
, your code would simply crash on runtime, because that property or function wouldn't be available on Fill
:
class Fill: Equatable {
func equals<T>(other: T) -> Bool where T: Fill { ... }
}
class Gradient: Fill {
private(set) var id: String = UUID().uuidString
override func equals<T>(other: T) -> Bool where T: Gradient {
return id == other.id // crash if `other` is value of type `Fill`
}
}
So, the compiler now prohibits you from adding incompatible constraints when overriding a function.
Now, there are basically two ways to fix the problem - change your code and avoid adding incompatible constraints in the overridden function or do a runtime check in the overridden function using as?
or type(of:)
to check if the passed value indeed satisfies the new constraints and then try using it:
override func equals<T>(other: T) -> Bool where T: Gradient {
if type(of: other) == Fill.self { return false }
return id == other.id // okay
}
Upvotes: 0
Reputation: 39
In my case I just fix this error by this:-
override func equals<T>(other: T) -> Bool where T: Fill {
guard let other = other as? Gradient else {
return false
}
...
}
But there are some similar errors of Macaw, So just replace Gradient with your error issue and it fix.
Upvotes: 0
Reputation: 325
Please look at this thread https://forums.swift.org/t/method-override-with-a-generic-signature-with-requirements-not-imposed-by-the-base-method/33593
This compilation error prevents you from future crashes.
Upvotes: 1