Live data from Hacker News

Group Borrowing: Zero-cost memory safety with fewer restrictions

verdagon.dev

71–80 of 87 posts

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#71

Earlier quoted context omitted.

That's the destructor function, that is written by you and called by Rust before actually destroying something. The function that you want to look at is [1]. If you read the docs at your link it even says: > This method is called implicitly when the value goes out of scope, and cannot be called explicitly (this is compiler error E0040). > However, the mem::drop function in the prelude can be used to call the argument…

The drop function being talked about here is the one I pointed to, not the one you pointed to. The Drop trait is built into the language (as a lang item), std::mem::drop is just a regular old function.

The drop that you mention doesn't free memory, as I understand, it is called before actually destroying object's memory.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#72
post #18

Earlier quoted context omitted.

Intriguing, what would be the purpose of such owning references compared to just passing ownership? Is that to have a way to reliably avoid memcopying large objects when passing them by value?

> Is that to have a way to reliably avoid memcopying large objects when passing them by value? I believe so, yes. Currently the only way to transfer ownership is by-value, and LLVM might optimize away the memcpy, but also it might not.

I wonder what is the case when you cannot optimize away memcpy, but can work around it with an "owning reference"?

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#73

Earlier quoted context omitted.

The drop function being talked about here is the one I pointed to, not the one you pointed to. The Drop trait is built into the language (as a lang item), std::mem::drop is just a regular old function.

The drop that you mention doesn't free memory, as I understand, it is called before actually destroying object's memory.

Not inherently, sure. But ultimately this is far afield of what I was trying to say, which is that the signature being discussed of being changed from &mut T to &owned T is the one from the Drop trait. That’s it.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#74
post #57

Earlier quoted context omitted.

The "Group Borrowing" concept that we're discussing still imposes aliasing restrictions to prevent unsynchronized concurrent access, and also to prevent "unplanned" aliasing. For example, for the duration of a function call, the default restriction is that a mut argument can only be mutated through the argument's identifier. The caller may be holding other aliases, but the callee doesn't need to be concerned about th…

> Borrowing happens for the duration of a function call I don't understand this part. Cannot a function store a borrowed reference into a structure that outlives the function?

Yes, functions can return non-owning references. However, those references do not "borrow" their target, in the sense that they lock others out. That is the Rust model, and OP does a great job covering its limitations.

So, with the understanding that "borrowing" means "locking others out", a group parameter borrows the group for the duration of the function call. If it borrows the group as mutable, no other group parameters can borrow the group. If it borrows the group as immutable, other group parameters are limited to borrowing the group as immutable. This is reminiscent of the Rust model, but the XOR rule applies to group parameters rather than references, and borrowing lasts the duration of a function call, rather than the lifetime of a reference.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#75
post #56
post #31

I’m pretty impressed, but also skeptical. There’s a contradiction in this post. Near the beginning of the post is a list of use cases for mutable aliasing. "Back-references", "doubly-linked lists", "delegates" - all cases where you have persistent objects with references to each other, i.e. a cyclic graph of objects. Near the end, the post says: “The mutual isolation restriction will influence our programs' data to l…

Hi there, I am the Nick whose design we're discussing. You raise some valid points: the blog post enumerates some limitations with Rust's model, but my design (as written) only resolves a subset of those limitations. We probably should have made that a bit clearer. That said, there is still hope! I have been iterating on the design over the last 9 months and am fairly confident that I can model graphs, as long as a f…

Good luck! I look forward to seeing the results.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#76
post #24

In memory-safety discussions it needs to be borne in mind that 'simply fix the hardware' is also a viable approach; or at least it's a lot more viable than it was or seemed to be a few decades ago https://en.wikipedia.org/wiki/Capability_Hardware_Enhanced_R... . Memory-safe BSD and applications running on real memory-safe RISC-V hardware apparently already exist, though obviously, yes, even in a best case existing ar…

Maybe it is because of Oracle's hate among the hacker community, however I always have to point out Solaris SPARC and Oracle Linux SPARC, have been shipping with ADI enabled since 2015, CHERI isn't the only option.

https://docs.oracle.com/en/operating-systems/solaris/oracle-...

https://www.kernel.org/doc/Documentation/sparc/adi.rst

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#77
post #9

I'm not sure if I understand it correctly. So, if I have a hashtable, adding or removing an element would invalidate existing pointers to any other element in the hashtable? I guess it makes sense from a memory release POV, but... I end up thinking that for databases using GC or RC is a better approach. Maybe I'm biased, but I have found far easier to work on databases written in C or C#. For that kind of programs I…

Rc is slightly expensive and Gc is super expensive. I would prefer a memory safety for free. As for C, it leaves verifying the safety up to you, it is not easy at all and I would rather spend time on something else using safe languages.

Alternatives have existed since the 1960's, predating C's invention, and also after it came to be, the problem has been mainstream adoption of UNIX, and the side effects from that.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#78

Earlier quoted context omitted.

Well the distinction between mutable and immutable borrows doesn't solve use-after-free. What prevents use-after-free is ownership. There is one owner, and the owner can not free the memory as long as there is a borrower (it doesn't matter whether the borrower is mutable or not). So that's the task of the borrow checker. For my own programming language [1], I have only mutable borrowers (similar to Java), and a much…

> There is one owner, and the owner can not free the memory as long as there is a borrower (it doesn't matter whether the borrower is mutable or not). So that's the task of the borrow checker. Yes, but what about: ``` let mut x = &mut some_vec; some_vec.push(10); ``` Sure the vec has an owner, but the second mutable borrow causes it to invalidate the first pointer. You need a _third_ category, “unstable mut”, which i…

Yes, I see your point. In Rust, the owner, and the mutable borrower can change the pointer itself (like C realloc). If multiple "mut" borrows are allowed, then this would be unsafe, so I understand "unstable mut" would solve this problem - but result in a new colouring problem.

My solution to this would be: in a new language, do not allow reallocation. Not for owners, and not for mut borrow. This is what Java does: an ArrayList is a wrapper around an array, and so adding entries will not move the ArrayList object, just the (wrapped) private array. In Java the programmer never sees dangling references. Java prevents the issue by design, at the cost of always paying for the wrapper. If you want to avoid this price, you need to use the array directly.

(I have to admit I was not aware that in Rust, push moves the memory... so thanks a lot for explaining! Always learning something new.)

I don’t have any problem with Rust’s focus on performance. But its design does make life harder for developers than it needs to be. It doesn't match my vision of a programming language that is at the same time easy to use, safe, and nearly as fast as C.

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#79
post #50

Earlier quoted context omitted.

Well the distinction between mutable and immutable borrows doesn't solve use-after-free. What prevents use-after-free is ownership. There is one owner, and the owner can not free the memory as long as there is a borrower (it doesn't matter whether the borrower is mutable or not). So that's the task of the borrow checker. For my own programming language [1], I have only mutable borrowers (similar to Java), and a much…

I'm looking forward to your experience with this approach! Bit off topic, but is there any particular reason you went with a go-like `ident type` syntax over the more common ones like the C or the ML one?

> any particular reason you went with a go-like `ident type` syntax

I just think that ":" is unnecessary. In my language, the type is mostly used in function declarations and types, eg.

    fun File read(data i8[], pos int, len int) int

    type List(T)
        array T[]
        size int
What would be the advantage of adding ":"?

Re: Group Borrowing: Zero-cost memory safety with fewer restrictions

#80

Earlier quoted context omitted.

> There is one owner, and the owner can not free the memory as long as there is a borrower (it doesn't matter whether the borrower is mutable or not). So that's the task of the borrow checker. Yes, but what about: ``` let mut x = &mut some_vec; some_vec.push(10); ``` Sure the vec has an owner, but the second mutable borrow causes it to invalidate the first pointer. You need a _third_ category, “unstable mut”, which i…

Yes, I see your point. In Rust, the owner, and the mutable borrower can change the pointer itself (like C realloc). If multiple "mut" borrows are allowed, then this would be unsafe, so I understand "unstable mut" would solve this problem - but result in a new colouring problem. My solution to this would be: in a new language, do not allow reallocation. Not for owners, and not for mut borrow. This is what Java does: a…

> ArrayList is a wrapper around an array, and so adding entries will not move the ArrayList object, just the (wrapped) private array.

That's also how Vec works in Rust. Vec is just (buf_ptr, capacity, len) where capacity is the allocated size of the buffer.

The problem still exists though.

``` let mut v = vec![1, 2 ,3]; let x: &i32 = &v[0]; v.push(4); println!("First element {x}"); ```

The `push` might realloc the array. Then, x points into invalid memory. This is caused by the projection: You can create a reference to a field (aka member) from a reference to the base object.

A language without realloc sounds painful. Any growing container would lead to stale data.

Post reply on HN