I stumbled against this wall a few times, previously I simply ignored it, but now it seems like a pointless language limitation. Every object type (right now we only have classes) in Swift is implicitly a subtype of AnyObject, which in fact is like a type alias to the class keyword. That makes any instance that is known to be of type AnyObject a reference type.
However when used in a protocol extension the compiler does not allow one mutate mutable members even if Self is guaranteed to be a AnyObject sub-type.
Here the original example that got me thinking:
protocol P {
var value: Bool { get set }
}
protocol Q {
associatedtype Object: AnyObject
var object: Object { get }
}
protocol R: Q where Object: P {}
extension R {
func makeTrue() {
object.value = true // Cannot assign to property: 'object' is a get-only property
}
}
Making P refine AnyObject solves the issue here, but it defeats the purpose of reusability of P in non-object context.
Another workaround would be this:
var ref = object
ref.value = true
However it really feels not natural, rather messed up I would say.
@timv actually reduced the example from above to a simpler form:
protocol P {
var value: Bool { get set }
}
extension P where Self: AnyObject {
func makeTrue() {
value = true // Cannot assign to property: 'self' is immutable
}
}
One can solve the problem here by making the method mutating, but this is again non-sense as class bound types don't allow mutating and in this case Self is known to be class bound.
I refer to this error:
class A {
mutating func foo() {} // 'mutating' isn't valid on methods in classes or class-bound protocols
}
So why exactly do we have this limitation in the language?