Pitch: `borrow` and `inout` declaration keywords

From the proposal draft, I get the idea that forming multiple borrow or inout bindings to members of the same struct value is prohibited if at least one of the bindings is inout:

struct T { var a: A; var b: B; var c: (A, B) }
var t: T

do { // Legal: multiple borrows
  borrow a = t.a
  borrow b = t.b
  borrow b2 = t.b
}

do { // Illegal: inout and borrow of one property
  inout a = &t.a
  borrow a2 = t.a // 🛑 Exclusivity violation
}

do { // Illegal: borrow and inout of one property
  borrow a = t.a
  inout a2 = &t.a // 🛑 Exclusivity violation
}

do { // Illegal: inout and inout of one property
  inout a = &t.a
  inout a2 = &t.a // 🛑 Exclusivity violation
}

Is that right? How about tuples?

do {
  inout (ca, cb) = &t.c
}

Is there any way to allow temporarily splitting the value into multiple distinct inout parts without any of the examples below being an exclusivity violation? With some new syntax, if need be?

do { // Could this be allowed?
  borrow a = t.a
  inout b = &t.b // ✅❔
}

do { // And this?
  inout a = &t.a
  inout b = &t.b // ✅❔
}

Sometimes I wish there was a way to pluck multiple properties of a value into a tuple value with a syntax something like t.(.a, .b, .c.0) for a tuple of type (A, B, A) or t.c.(ca: .0, cb: .1) for the tuple type with labels (ca: A, ca: B). Maybe something like that could be used to pluck out multiple inout bindings at once without an exclusivity violation, as long as the members are distinct in memory?

do { // Future direction?
  inout (a, b, ca) = &t.(.a, .b, .c.a)
}
1 Like