“Cannot assign […] is a 'let' constant” with AnyObject

In this function I tried writing, the compiler outputs a Cannot assign through subscript: 'object' is a 'let' constant error—even though the object in question conforms to AnyObject, and is therefore a reference type, from what I think I understand. What am I missing?

func setIfDifferent<O: AnyObject, V: Equatable>(
	_ object: O,
	_ valueKeyPath: WritableKeyPath<O, V>,
	value newValue: V
) {
	guard object[keyPath: valueKeyPath] != newValue else {
		return
	}
	
	object[keyPath: valueKeyPath] = newValue
}

(one option to make the function work is to mark object as inout, but I'd like to understand why the current version doesn't work)

1 Like

You'll prolly need to use ReferenceWritableKeyPath as the key path parameter here.

2 Likes

I believe you should declare your function parameter as
_ object: inout O

Edit: :man_facepalming: Ah, you're not changing the object reference itself, no need for inout.

Ohhh, that was it, thank you! It didn't occur to me to look into the key path type itself.

1 Like

Yeah it is a little atypical; if I recall, the key path machinery was introduced before conditional conformances were available, so it unfortunately uses a class hierarchy of capabilities instead.

1 Like