At the moment, a property in a class-constrained protocol extension, where the protocol does not impose a class-requirement, would have a mutating setter by default. For example:
protocol P {}
class A: P {
var property: String = ""
}
extension P where Self: A {
var wrappingProperty: String {
get { return property }
set { property = newValue }
}
}
let instance = A()
instance.wrappingProperty = "" // Cannot assign to property: 'instance' is a 'let' constant
@Joe_Groffmentioned that this is a bug, because even though the protocol does not impose a class constraint, it's implied by the Self: A requirement in the extension, so wrappingProperty's setter should be non-mutating instead. This was fixed today (but it's being reverted now).
However, it's been bought to attention that the new behaviour can be source breaking in some cases. For example:
protocol P {
var property: String { get set }
}
extension P where Self : AnyObject {
var wrappingProperty: String {
get { property }
// This will now error and ask the user to explicitly
// mark the setter as mutating.
set { property = newValue }
}
}
What is the best way to handle this? Is the behaviour acceptable or does this change need to go through Swift Evolution? or should we leave this unfixed? cc @John_McCall@Douglas_Gregor
It's worth noting that what is potentially source breaking is the declaration site only and not any use sites.
Currently, wrappingProperty can't be set for anylet constant; if the issue is fixed, then that's the case only when it wraps a property that can potentially reassign self.
I think the best way to handle this is to improve the diagnostic that's emitted where there is source breakage: explain to the user that the setter must be marked as mutating because property is a protocol requirement that can reassign self; if the protocol is under the user's control as well, offer both fix-its (mark the setter of wrappingProperty as mutating, or mark the protocol requirement property as nonmutating set).
Do we have examples of source breakages in the compat suite?
Also, this breakage example mentioned here - should it error, in fact? Isn't the extension being constrained to AnyObject imply mutating?
I think this is unquestionably just a bug that should be fixed and doesn’t require evolution approval. Xiaodi’s point that such an implementation can’t actually be used is important.
Thanks! Could you raise this with the Core Team? Or is it not necessary? Once I get confirmation, I can go ahead and un-revert the patch and tweak the diagnostics.