swift
345b4cc0 - [region-isolation] Assigns to var with structs/tuples with multiple fields should be merges for now.

Commit
2 years ago
[region-isolation] Assigns to var with structs/tuples with multiple fields should be merges for now. The reason that this is being done is that since currently region based isolation is not field sensitive, when we assign to the struct or tuple field of the var, the new region relationship is set for the entire struct, not just a specific field. This means that we effectively lose any region information from the other fields. For example in the following at (1), given the current rules, we lose that s.y was assigned to x: ```swift struct S { var x: NonSendableKlass var y: NonSendableKlass } func foo() { var s = S() // Regions: [s] let x = NonSendableKlass() let y = NonSendableKlass() // Regions: [(s), (x), (y)] s.y = x // Regions: [(s, x), (y)] s.x = y (1) // Regions: [(x), (s, y)] } ``` The best solution to this is to track such var like bindings in a field sensitive manner where the regions of the aggregate are the union of the individual fields. This would let us represent the regions of the above as follows: ```swift func foo() { var s = S() // Regions: [((s.x), (s.y))] let x = NonSendableKlass() let y = NonSendableKlass() // Regions: [((s.x), (s.y)), (x), (y)] s.y = x // Regions: [((s.x), (s.y, x)), (y)] s.x = y (1) // Regions: [((s.x, y), (s.y, x))] } ``` We cannot do this today so to plug this hole, we instead treat these operations as merges. This provides a conservative answer. Thus we would have:" ```swift func foo() { var s = S() // Regions: [s] let x = NonSendableKlass() let y = NonSendableKlass() // Regions: [(s), (x), (y)] s.y = x // Regions: [(s, x), (y)] s.x = y (1) // Regions: [(s, x, y]) } ``` This is because we are treating the assignment into s.y and s.x as merges into s, so we do not lose that y was assigned into s before we assigned y into it. The unfortunate side-effect of this is that if a struct or tuple has multiple fields, the merge makes it so that if we assign over the same field, we do not lose the region of the old value: ```swift func foo() { var s = S() // Regions: [s] let x = NonSendableKlass() let y = NonSendableKlass() // Regions: [(s), (x), (y)] s.y = x // Regions: [(s, x), (y)] s.y = y (1) // Regions: [(s, x, y]) } ``` If we were not to do this, then the s.y at (1) would result in s and x being in different regions. rdar://117273952
Author
Committer
Parents
Loading