Why doesn't the example violate SE-0176 (Exclusive Access to Memory)?

Yes.

The nonmutating version of modifyX is roughly equivalent to the global function

func modifyX(_ self: Foo, _ foo: inout Foo)

while the mutating version of modifyX is roughly equivalent to

func modifyX(_ self: inout Foo, _ foo: inout Foo)

. There are no exclusivity violations if self and foo are the same in the first function since only foo is passed by reference. However, the second function does violate exclusivity if self and foo are the same because both self and foo are passed by reference.

The point of the law of exclusivity is to make it such that each variable has its own contents. If two variables stored the same contents, things could get confusing. If you wrote the following code:

func bar(_ x: inout Int, _ y: inout Int) {
    x += 1
    y += 1
}

you’d probably expect to be mutating two different variables. But if you passed the same variable for both parameters (i.e. bar(&baz, &baz)), then x and y would refer to the same variable and you’d mutate the same instance twice. The law of exclusivity prevents this unexpected behavior.

Allowing variables to alias each other can also affect the compiler’s ability to optimize your code (see the “Aliasing” section of this blog post if you want more details).

3 Likes