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?