|
|
Subscribe / Log in / New account

Rust 1.77.0 released

Version 1.77.0 of the Rust language has been released. Changes include support for NUL-terminated C-string literals, the ability for async functions to call themselves recursively, the stabilization of the offset_of!() macro, and more.

to post comments

Rust 1.77.0 released

Posted Mar 22, 2024 10:09 UTC (Fri) by josh (subscriber, #17465) [Link] (6 responses)

People have been wanting `offset_of!` for a very long time, and in lieu of a standard version have been writing versions in crates, many of which invoked undefined behavior. I'm glad we have a stable version now.

Rust 1.77.0 released

Posted Mar 22, 2024 12:51 UTC (Fri) by intelfx (subscriber, #130118) [Link] (5 responses)

> and in lieu of a standard version have been writing versions in crates, many of which invoked undefined behavior

Got an example?

Rust 1.77.0 released

Posted Mar 22, 2024 21:23 UTC (Fri) by josh (subscriber, #17465) [Link] (1 responses)

See https://rust-lang.github.io/rfcs/3308-offset_of.html#motivation .

Rust 1.77.0 released

Posted Mar 22, 2024 22:55 UTC (Fri) by tialaramex (subscriber, #21167) [Link]

That document says that memoffset and bytemuck both have offset_of! implementations but doesn't tell us whether either (or both) were problematic (e.g. Unsound or give wrong answers), or had been in the past.

It does report some problems (which the new definition presumably doesn't have) as motivation, but they're not soundness or correctness AFAICT.

Rust 1.77.0 released

Posted Mar 22, 2024 23:31 UTC (Fri) by geofft (subscriber, #59789) [Link] (2 responses)

Some explanation in the documentation for the standard library macro addr_of!, as well as a 2019 issue in one of the third-party crates that was only resolved when addr_of! got added (in Rust 1.51, March 2021).

As I understand it, the basic problem is that Rust's & operator gets you a reference, not a raw pointer. A raw pointer is basically like a C pointer; it doesn't really make any promises about pointing anywhere useful. A reference is in memory just a pointer too, but the semantics are different and basically the biggest thing that makes Rust special: it's a guarantee that the thing it points to is valid (has not yet been deallocated/freed) and that at any given time there is either at most one non-const (&mut) reference or that all references are const. The obvious / conventional way to implement offset_of is to make a null pointer of type pointer to the struct in question, index into the field in question, take its address, and return as an integer (see e.g. the most recent C implementation in Linux). But if you implement this in Rust, even if you start with a raw null pointer 0 as *const Foo, indexing into a field and taking the address gets you a reference, not a null pointer - and it is a thoroughly invalid reference, and so it is undefined behavior.

The implementation of addr_of! uses the syntax &raw (which is not yet available in stable Rust, but the standard library can use it), which immediately creates a raw pointer, not a reference, avoiding the undefined behavior.

The other approach is to start with an actual object (or just a reference to one), which gives you no trouble constructing a real reference to one of its members. But that requires the object to exist. You can't necessarily create an object of an arbitrary type; you may have to call its constructor, which might not be possible without an unwanted side effect (consider std::fs::File or std::process::Child). There was a prior issue in that same third-party crate due to creating a reference to an object that was not properly constructed, though resolving this issue did not by itself remove all the UB in that crate.

(Also, it took me about an hour to come up with this comment and be at least somewhat confident it was correct - I had previously written out a totally different analysis based on misunderstanding the validity of raw pointers themselves - which is by itself another good reason that this should be encapsulated in some super obvious standard library facility instead of expecting people to get it correct on their own, even if technically they could.)

Rust 1.77.0 released

Posted Mar 23, 2024 13:10 UTC (Sat) by intelfx (subscriber, #130118) [Link] (1 responses)

Thank you! That was a fun rabbit hole — and, incidentally, the first time I saw a "theoretical" UB — like creating a zeroed reference, or taking a reference to uninitialized memory, without reading from it — actually causing crashes (e.g. that memoffset crate used to trap on ARM).

Rust 1.77.0 released

Posted Mar 25, 2024 2:28 UTC (Mon) by NYKevin (subscriber, #129325) [Link]

I would tend to imagine there are probably situations where you can persuade CHERI or Itanium to fault on "theoretical" UB, but you might need the optimizer's help to get over the finish line (at which point it's really a function of how creative your optimizer is, rather than a function of the architecture per se).

Rust 1.77.0 released

Posted Mar 22, 2024 23:14 UTC (Fri) by tialaramex (subscriber, #21167) [Link] (4 responses)

zero terminated C-style string literals is a really nice convenience for those people (presumably more in the kernel and adjacent communities) who need this type. Completely irrelevant to make 90% of Rust users and yet very important to some, and I think the core language is the only place you could really do this, at least with reasonable ergonomics.

I'm actually not sure what (if any) mechanism existed to write a constant (not just immutable) &CStr in stable before this landed, and obviously if you do a bunch of C interop that's pretty annoying. Constant &str was easy - that's what ordinary "string literals" are in Rust anyway.

Rust 1.77.0 released

Posted Mar 23, 2024 14:24 UTC (Sat) by rodrigorc (guest, #89475) [Link]

Not only for the kernel or bare targets. Any direct interaction with an existing C library will need a `&Cstr` sooner or later.

I used to use the `cstr` crate (https://docs.rs/cstr), that provides a `cstr!` macro and was able to build a const `&'static CStr`.

But this syntax is much nicer `c"hello"` vs `cstr!("hello")`.

Rust 1.77.0 released

Posted Mar 23, 2024 15:00 UTC (Sat) by atnot (subscriber, #124910) [Link] (2 responses)

> I'm actually not sure what (if any) mechanism existed to write a constant (not just immutable) &CStr in stable before this landed.

It wasn't too hard, just a bit annoying. There's a const constructor for it from bytes:

https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html...

It does require a null terminator, but in const context forgetting that is a compile error and it's fairly easy to wrap in a macro anyway, though not as pretty.

Rust 1.77.0 released

Posted Mar 23, 2024 22:28 UTC (Sat) by intelfx (subscriber, #130118) [Link] (1 responses)

> It wasn't too hard, just a bit annoying. There's a const constructor for it from bytes:
>
> https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html...
>
> It does require a null terminator, but in const context forgetting that is a compile error

I'm probably clueless, but how do you make CStr.from_bytes_with_nul() generate a compile error? It returns Result, and .unwrap() does not seem to be const.

Rust 1.77.0 released

Posted Mar 24, 2024 8:55 UTC (Sun) by bluss (guest, #47454) [Link]

You call panic if it is None https://rust-lang.github.io/rfcs/2345-const-panic.html


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