|
|
Subscribe / Log in / New account

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Sep 29, 2025 16:29 UTC (Mon) by daroc (editor, #160859)
In reply to: "Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other," by theodorvaryag
Parent article: Comparing Rust to Carbon

I'm sure there is a way to represent something like this in Rust, but I don't think your proposed solution is quite it. In the wrapper function, you're taking input as an &[u8], but output as a &mut [u8]. Those references can't alias, so there's no way to actually call the wrapper in a way that would update the input buffer in-place, I think. And even if you could, the compiler might break things while optimizing because you changed the data under a &[u8], which isn't permitted.

If I were trying to encapsulate this interface in safe Rust, I might use an enum type that contains either a normal reference or a mutable reference, and checks things at run time that way. But I'd need to think about the API design a bit more to be confident in that approach.


to post comments

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Sep 29, 2025 22:28 UTC (Mon) by theodorvaryag (guest, #179596) [Link] (1 responses)

>Those references can't alias, so there's no way to actually call the wrapper in a way that would update the input buffer in-place, I think.

>And even if you could, the compiler might break things while optimizing because you changed the data under a &[u8], which isn't permitted.

https://github.com/bitemyapp/mut-ref-ptr-alias

You can `git clone` this repository and run the tests under Miri with `make test`. When I tested an incorrect version (calling as_mut_ptr multiple times) _that_ failed Miri. Calling `as_mut_ptr` and then deriving the aliased pointers from the original `as_mut_ptr` is not UB. Even with the unsafe code Rust can help you manage exclusive use/derivation of the original mutable pointer from the mutable reference if you like.

The optimizer won't break anything because it understands pointers can be aliased. These test cases all pass Miri. I work on a VM/interpreter that uses unsafe, raw pointers, and the like in Rust extensively: https://github.com/zorp-corp/nockchain/tree/master/crates...

If there's something these examples don't cover or you think Miri is wrong about this not being UB, please tell me so I can add more test cases or file a bug with Miri.

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Sep 30, 2025 13:12 UTC (Tue) by daroc (editor, #160859) [Link]

Thank you for the detailed example; it's always great to discuss concrete code. See my other comment for a response about the API, but for other readers following along at home:

Unless I'm misunderstanding something, these examples use *mut [u8] at the same time as a *const [u8], which I agree won't cause any problems. The part I thought would be broken is using a &mut [u8] at the same time as a &[u8] pointing to the same memory.

Here's one of your example tests lightly modified to use references instead of pointers:
https://play.rust-lang.org/?version=stable&mode=debug...

Running it via MIRI does show that it triggers undefined behavior.

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Sep 29, 2025 22:28 UTC (Mon) by theodorvaryag (guest, #179596) [Link] (3 responses)

>you're taking input as an &[u8], but output as a &mut [u8].

Yeah this is incidental to me scaffolding a hypothetical API while very tired (I have a newborn, 4 children besides, and I didn't sleep much last night)

You can represent it as a single &mut [u8] and fan-out the aliased pointers behind the "safe" API. You can do more or less whatever you need/want to do and put a safe wrapper around it, I was just hewing too closely to the C FFI rough sketch in the safe API wrapper.

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Sep 30, 2025 13:04 UTC (Tue) by daroc (editor, #160859) [Link] (2 responses)

I think we all wish we could get more sleep sometimes; I hope your newborns are well.

But yes, if you use a single &mut [u8], I agree that there isn't a problem. So I do believe it should be possible to safely wrap this interface by using a type like this:

    enum Example<'a> {
        InPlace(&'a mut [u8]),
        OutOfPlace { from: &'a [u8], to: &'a [u8] },
    }

I can't speak for Carruth, obviously, but given my understanding of his talk, I think his response would be something like: "But the point is that introducing a Rust API like that involves doing extra work to reshape the API, which complicates a piece-by-piece rewrite from C++; with Carbon, a piece-by-piece rewrite can do the initial change of languages and the cleanup of the API as separate, more easily understood steps."

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Oct 7, 2025 8:53 UTC (Tue) by roc (subscriber, #30627) [Link] (1 responses)

Or you could reshape the API on the C++ side before you move code to Rust.

This is a pretty weak motivation for Carbon IMHO.

"Trying to represent this API in Rust just doesn't work. The language never lets mutable references alias each other,"

Posted Oct 8, 2025 2:04 UTC (Wed) by smurf (subscriber, #17840) [Link]

> Or you could reshape the API on the C++ side

That was my first thought too. I mean, the caller of this thing knows whether it's the same buffer or not. In-place modification in general allows for different optimizations than knowing that two regions don't alias.

IMHO the more apt comparison isn't greenfield vs. brownfield but, quite plainly, a culture where the C[++] users see the new kid on the block as an opportunity to clean up their own act i.e. their own interfaces, thus improving the C side of the codebase as well … or not.

Since the "or not" side is already served perfectly well by simply continuing to use C, for some value of "perfectly well" anyway. I kindof doubt that Carbon will get much traction. Which is for the best really (again IMHO): I'd rather see one effort to replace C++ with something sane+safe actually succeed, long-term, than three such projects, all with somewhat-conflicting goals and all fighting for developer mindset, not to mention time.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds