Cannot assign to property; 'self' is immutable

Here's the scenario. A protocol Paintable requires a property primaryColor with a getter and setter.


protocol Paintable {

  var primaryColor: UIColor { get set }
  
}


Paintable is extended to provide a default getter and setter for primaryColor.


extension Paintable {

  var primaryColor: UIColor {
    get { return UIColor.blackColor() }
    set { }
  }

}


The empty setter is necessary. Otherwise, an adopting type that does not implement primaryColor gets the "does not conform to protocol" error. So this would lead me to believe that, by writing the empty setter, the protocol requirements are satisfied.


However, in a type that adopts Paintable but does not implement primaryColor, the getter works fine, but attempting to set primaryColor gets an error.


class Car: Paintable {

  func paintNewColor(color: UIColor) {
    print(primaryColor) // Works fine
    primaryColor = color // Generates error: cannot assign to property: 'self' is immutable
  }

}


Of course, if Car implements primaryColor as a variable, the setter works fine.


class Car: Paintable {

  var primaryColor = UIColor.whiteColor()
  
  func paintNewColor(color: UIColor) {
    print(primaryColor) // Works fine
    primaryColor = color // Works fine
  }

}


Is this intended behavior?

Two ways I know to solve it:


Enforce mutability of the property:

protocol Paintable: class


Deliberately mark the potential mutation:

struct Car: Paintable {
  mutating func paintNewColor(color: UIColor) {

Thanks Jessy! Declaring the protocol as class-only resolved the issue. Do you know why this is necessary, though--or is this unintentional behavior? Because only structures need to (and can) mark a mutating function as mutating, and the compiler should be able to recognize that my function is in a class.

It seems to me like the compiler should have been able to deal with your code, but it's possible that we're not thinking of some potential problem.

I agree - you should bug this.

Done: 22775273

Cannot assign to property; 'self' is immutable
 
 
Q