Any languages using "shared mutable borrow refs", or things like group borrowing?
Hey all, I'm trying to collect a list of languages that are using (or experimenting with!) shared mutable borrow refs.
A shared-mutable borrow reference is a memory-safe reference that has no run-time overhead (no GC, refcounting, nor generations). It lets you do something like this (using Rust-ish syntax):
func main() {
let ship: Ship =
Ship{ fuel: 100 };
// Two refs pointing at the same ship
let ref_a = &shmut ship;
let ref_b = &shmut ship;
// You can use both references to modify the ship
ref_a.fuel += 20;
ref_b.fuel -= 8;
print(ref_a.fuel); // Prints 112
}
Of course, they have limitations; they can't reach into Vec elements, through pointers, or into unions safely. For example:
func main() {
let fleet: Vec<Ship> =
vec![
Ship{fuel: 100},
Ship{fuel: 100}
];
let ref_a = &shmut fleet[0];
fleet.clear();
ref_a.fuel += 20; // UH OH, crash
}
To address this, some languages add unique references in (like Rust's &mut), like:
func main() {
let fleet: Vec<Ship> =
vec![
Ship{fuel: 100},
Ship{fuel: 100}
];
let ref_a = &uniq fleet[0];
ref_a.fuel += 20;
print(fleet[0].fuel); // 120
}
With some special rules to prevent us from accessing anything else that might alias it while we're doing things with the unique reference. Ante does this with its temporary unique conversions.
Even that has limitations though (we can only borrow one element at a time), and so Ante and a few other languages are looking at group borrowing to support "invalidation" like below:
func main() {
let fleet: Vec<Ship> =
vec![
Ship{fuel: 100},
Ship{fuel: 100}
];
// Can have &shmut refs pointing at elements of Vec
let ref_a = &shmut fleet[0];
let ref_b = &shmut fleet[1];
// Can modify through them
ref_a.fuel += 20;
ref_b.fuel -= 8;
fleet.clear(); // Erase all ships
// ref_a.fuel += 50;
// Compile error: ref_a was invalidated by `clear` call.
// ref_b.fuel -= 3;
// Compile error: ref_b was invalidated by `clear` call.
}
Basically, group borrowing:
- Tracks that
ref_a's type is actually&Ship in fleet[]; it tracks where the pointer is pointing to. - Requires functions to express what they're modifying;
clear's signature says that it's modifyingself's contents. - Invalidates any references (like ref_a and ref_b) that are pointing inside an object that a function said it modified.
As far as I know, these are all the languages investigating some form of group borrowing:
- Carbon (talk, slides)
- Mojo (roadmap, some recent work)
- Ante
- Conjure
- Fang
- Plecra/Vi is working on something called "Exclusion typing"/the exclusion calculus"
- (My own stuff, but thats a whole 'nother story)
- Anyone else?
(Note I'm not really counting things like Pony and Verona since they're GC'd)
I want to write a followup article about group borrowing soon, and I'd love to hear about any of you that are exploring it or anything similar.
Cheers!