-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
We can only call setfield! on a mutable, so calling it on a immutable has been an error. This makes it hard to efficiently construct immutable objects incrementally. To fix, we propose making it possible to have setfield! modify fields inside of immutable objects that are wrapped in mutable objects. As will be shown later, this wouldn't alter existing semantics. This proposal also is an implementation of the concept that the object nursery is editable and then the object should be come immutable when done constructing it.
To support this proposal, the setfield! function will get a multi-arg form, with the following behaviors:
setfield!(x, a, b, c, value) mutates the right most mutable object to change the value of its fields to be equivalent to copying the immutable objects and updating the referenced field.
Then in the front-end, we will lower the syntax form x.a.b.c = value to the multi-arg setfield! (instead of the current lowering that mixes setfield! and getfield). In the mutable case, this will not change any behavior since it still assigns to the right-most field. In the immutable case, it would now be possible to assign through a mutable object, resulting in a transparent/fused copy/assignment that maintains the semantics of both the update of a mutable field with a new copy, and the fixedness of the immutable value. This lowering change has precedent, since it would be semantically similar to the way that setindex! is handled. Oscar tells me that Inference already has the logic to ensure this lowers efficiently to avoid allocating extra values, and codegen will also be able to handle this efficiently.
tl;dr The syntax:
x.a.b.c = 3would now be valid, as long as at least one of the referenced fields is mutable.
(opened at the insistence of @carnaval, to summarize recent discussions)