Live data from Hacker News

Ante: A new way to blend borrow checking and reference counting

verdagon.dev

21–30 of 31 posts

Re: Ante: A new way to blend borrow checking and reference counting

#21

I can see how multiple mutable references is fine in a single-threaded context, but surely this would cause UB in the multi-thread context?

Jake has already mentioned how the type system enforces single-threading (using similar mechanisms as Rc in Rust), but it's not necessarily the case that read-write races from multiple threads are UB.

In particular, Java allows aggressive multithreaded access, and the memory model has some pretty strong guarantees. Informally stated, if a read and a write race, then the read is guaranteed to observe either the old or new value.

Go is something of a middle ground [1]. Races on simple scalar values are not UB, but "fat pointers" (slices and interfaces) can tear and can lead to "arbitrary memory corruption."

When I was reading about "stable shape" I was wondering if it might be something similar. You easily get the same UB problems when dealing with sum types, as a tear across tag and variant payload can cause all kinds of things to go wrong.

[1]: https://go.dev/ref/mem

Re: Ante: A new way to blend borrow checking and reference counting

#22
post #11

I can see how multiple mutable references is fine in a single-threaded context, but surely this would cause UB in the multi-thread context?

Creator of Ante here, Ante inherits Rust's Send/Sync for thread-safety. `mut` refs and `Rc` which provides shared mutability don't implement either and thus can't be shared across threads. So shared mutability is only within a single thread.

OOI why did you go with RC at the lattice bottom rather than generational refs? Not sure how in touch you are with the author of Vale?

What would be good is if effects are used to discharge the ownership obligations, that should dovetail well in Ante. BTW I appreciate the clear effects handling in Ante, very nice!

Re: Ante: A new way to blend borrow checking and reference counting

#23
The interesting bit here is treating Rc and &T as compatible via a shared representation, so you can hand an Rc to a function expecting a borrow without bumping the count. Swift already does something adjacent with its guaranteed vs owned parameter conventions eliding retain/release pairs, but that's an optimization pass, not a type-level guarantee. Making it explicit in the signature is nicer because you can reason about when a clone actually happens.

The part I'm skeptical about is cycles. Once you lean on RC as the escape hatch for graph-shaped data, you inherit the weak-reference discipline problem that Rust users hit with Rc>. Ante doesn't seem to address that directly, and region inference has historically been fragile at scale (see the ML region work that got abandoned for tracing GC). Also, if a borrowed T is really a pointer into an Rc allocation, you need to guarantee the count can't hit zero during the borrow, which either requires the caller to hold the Rc live across the call or some form of stack pinning. Curious how they handle re-entrancy through a callback that drops the last strong ref.

Re: Ante: A new way to blend borrow checking and reference counting

#24
post #11

Earlier quoted context omitted.

Creator of Ante here, Ante inherits Rust's Send/Sync for thread-safety. `mut` refs and `Rc` which provides shared mutability don't implement either and thus can't be shared across threads. So shared mutability is only within a single thread.

OOI why did you go with RC at the lattice bottom rather than generational refs? Not sure how in touch you are with the author of Vale? What would be good is if effects are used to discharge the ownership obligations, that should dovetail well in Ante. BTW I appreciate the clear effects handling in Ante, very nice!

> Not sure how in touch you are with the author of Vale?

FYI - this article is written by the author of Vale

Re: Ante: A new way to blend borrow checking and reference counting

#26
Interesting but I wonder how useful this is in practice. It doesn't work with unions/enums, I presume it also doesn't work with heap allocated containers, like vectors, hash maps, etc? Wouldn't that rule out like 90% of typical data structures?

Also, there's definitely something to be said for Rust's ownership rules improving code quality. I wonder if that would be affected if you relax them like this?

Very interesting anyway!

Re: Ante: A new way to blend borrow checking and reference counting

#27

I'm really looking forward to the next generation of languages. Not only are the old 90's languages like Java, PHP, and JavaScript now actually doing things correctly. The new languages like Zig, Go, Swift and Rust continue to figure out new ways of trying things like generics. Spinoffs like V, Ante, and others are perfect testing grounds.

>I'm really looking forward to the next generation of languages.

me too!

Re: Ante: A new way to blend borrow checking and reference counting

#28

What if I omit the "uniq" keyword? Is it still valid code, just not protected by the compiler from union types changing underneath?

Most uses of `uniq` in the article aren't necessary and are just included for explicitness. Anywhere a `uniq` ref is required but you only have a `mut` ref, Ante will convert it to a `local uniq` ref with the various rules required while it is still in scope. So you'll still be protected and will get the same compile errors if you try to access an alias while the locally unique reference is still alive.

Re: Ante: A new way to blend borrow checking and reference counting

#29
post #23

The interesting bit here is treating Rc and &T as compatible via a shared representation, so you can hand an Rc to a function expecting a borrow without bumping the count. Swift already does something adjacent with its guaranteed vs owned parameter conventions eliding retain/release pairs, but that's an optimization pass, not a type-level guarantee. Making it explicit in the signature is nicer because you can reason…

Creator of Ante here, passing `Rc` as `&T` or `&Rc` is a somewhat standard practice Ante inherits from Rust and C++ here.

As for cycles, `Rc t` in Ante isn't magic and when used in cycles it will leak. Ante does not use region inference, just the related, derived field of borrow-checking. The family tree there roughly resembles MLKit -> Cyclone -> Rust -> Ante in that regard.

When borrowing the inner element of an `Rc t`, the type system ensures that the resulting `ref t` cannot be dropped while it is still held. In particular, dereferencing an `Rc t` requires a unique value, but only gives you a shared value to the element: `Rc.as_mut: fn (uniq Rc t) -> mut t`. In practice, this means if you only have a shared ref to an Rc but need a reference to the element inside, you either need to clone the outer Rc (guaranteeing it won't be dropped while the borrow is alive), or use the local uniqueness conversion and avoid using any possible aliases while using the reference.

Re: Ante: A new way to blend borrow checking and reference counting

#30
post #4

>"I have to admit, this is beautiful" Terse it is, beautiful it is not (well my version of beautiful that is - easy to read and understand). this is not to diminish the language.

surprised to see that, I've long held tree balancing up as practically the poster child for ML syntax being the best way to express certain algorithms. it directly says what shape of nodes goes to what other shape.
Post reply on HN