> Adding a default implementation for a protocol requirement shouldn't stop existing types that correctly conform to that protocol from compiling.
I would disagree with that; adding that default implementation is not a simply internal change. It flat-out changes compilibility; it makes invalid code into valid code:
protocol P {
func f()
}
class C : P {} // Error!
---
protocol P {
func f()
}
extension P {
func f() {}
}
class C : P {} // Okay
Given the trap demonstrated here, the converse should hold as well. Doubly so in light of the ways the compiler (mostly helpfully) enforces various aspects of subclassing, as you pointed out.
In many ways, protocols (right now at least) feel like Swift having its cake but not eating it: strictness floats around them in ways that do not help developers (ugh, PATs!) but is absent where it would:
// This all compiles without any warnings?!
protocol P {
var i: Int { get set }
}
protocol Q : P {
var i: Int { get }
}
class C : Q, P {
var i = 10
}
// Now make a protocol that inherits from another,
// where both are class/AnyObject constrained
//---
struct S : Hashable { // Swift 4.1, synthesized
let s: String
}
extension S : Equatable {
static func == (lhs: S, rhs: S) -> Bool {
// Hashable semantics, smashable semantics. Hold my beer.
return lhs.s.first == rhs.s.first
}
}
I would disagree with that; adding that default implementation is not a simply internal change. It flat-out changes compilibility; it makes invalid code into valid code:
--- Given the trap demonstrated here, the converse should hold as well. Doubly so in light of the ways the compiler (mostly helpfully) enforces various aspects of subclassing, as you pointed out.In many ways, protocols (right now at least) feel like Swift having its cake but not eating it: strictness floats around them in ways that do not help developers (ugh, PATs!) but is absent where it would: