Though, for my example, the storage location of the array metadata/fat pointer is not relevant.
In Rust you can hold references directly into the buffer backing the array (`&v[0]`).
My Java knowledge is quite rusty at this point. AFAIK, a `ArrayList<MyType>` in Java stores pointers to MyType in the buffer. So, when indexing into a ArrayList, you never hold references into the actual buffer. Instead you get a shared-pointer to the class data. It's the indirection of the array entry that saves you during reallocation of the buffer.
Also because Java is a GC'ed VM, it wont dealloc the elements references by the array, as long as there are other references to an element.
The equivalent in Rust is `Vec<Rc<MyType>>` where holding an `&Rc<MyType>` referencing into the vec's buffer is problematic during reallocation. But, cloning the Rc and holding on to it is perfectly fine.
The initial point of this thread was that you can have a Rust-like language where you can hold multiple mutating (aliasing) references and prevent use-after-free. This won't work. Without a GC or RC, you can use one reference to "rug-pull" the memory that is aliases by the other reference.
> In Rust you can hold references directly into the buffer backing the array
Yes! But I am arguing that this prevents having multiple mutable references
> My Java knowledge is quite rusty
> Also because Java is a GC'ed VM ...
Your Java knowledge is fine :-) But I'm arguing that you don't strictly need a GC'ed, or RC'ed language: if done "correctly", multiple mutable references are possible. Just not with fat pointers! The programming language I'm building allows this even today. You can try it in the playground [1]:
fun main()
list := List+(int[4]) # <<= owned list
borrow : &list # <<= mutable borrow
for i := until(4)
borrow.add(i)
list.add(10 * i)
for i := until(8)
println(borrow.array[i])
type List
array int[]
size int
fun List+ add(x int)
if size >= array.len
n : int[array.len * 2]
for i := until(array.len)
n[i] = array[i]
array = n
array[size] = x
size += 1
So "List+" is owned type (just "List" without "+" would be reference counted). You may want to look at the generated C code at the end of the page.
You are borrowing the entire list. That’s fine. The problem occurs if you borrow a reference into the list. Java/C# solve this by making that operation impossible. You cannot hold a reference into a vector/list
Though, for my example, the storage location of the array metadata/fat pointer is not relevant.
In Rust you can hold references directly into the buffer backing the array (`&v[0]`).
My Java knowledge is quite rusty at this point. AFAIK, a `ArrayList<MyType>` in Java stores pointers to MyType in the buffer. So, when indexing into a ArrayList, you never hold references into the actual buffer. Instead you get a shared-pointer to the class data. It's the indirection of the array entry that saves you during reallocation of the buffer.
Also because Java is a GC'ed VM, it wont dealloc the elements references by the array, as long as there are other references to an element.
The equivalent in Rust is `Vec<Rc<MyType>>` where holding an `&Rc<MyType>` referencing into the vec's buffer is problematic during reallocation. But, cloning the Rc and holding on to it is perfectly fine.
The initial point of this thread was that you can have a Rust-like language where you can hold multiple mutating (aliasing) references and prevent use-after-free. This won't work. Without a GC or RC, you can use one reference to "rug-pull" the memory that is aliases by the other reference.