protocol P {
var getSetProp: Int { get set }
}
func updateComposition<T: P & AnyObject>(_ object: T) {
object.getSetProp = 42
// `- error: cannot assign to property: 'object' is a 'let' constant
}
protocol Q: AnyObject {
var getSetProp: Int { get set }
}
func updateInheritance<T: Q>(_ object: T) {
object.getSetProp = 42 // β
}
why is there an error when setting the property in the protocol composition case, but not in the protocol inheritance case?
The key thing is that a mutating setter on a non-class constrained protocol can actually fully replace self, which a class cannot. (all the details are in the Masto thread)
Guys, I think you are missing this <T: P & AnyObject> part in OP.
Conceptually, a compiler could judge it legal to promote a mutating set into a nonmutating set when we can tighten the constraint on the target object (from P tp P & AnyObject). I cannot come up with any semantic bad cases (and I'm wrong, see Dante's post).
It's just the current design of protocol composition cannot easily implement this. After OP's code get compiled, there just does not exist a witness symbol in the binary with the semantics of P.getSetProp.nonmutating_set that can be called on object.