Hacker News new | past | comments | ask | show | jobs | submit login
Rust 1.52.0 (rust-lang.org)
109 points by steveklabnik 8 months ago | hide | past | favorite | 31 comments



As a Rust total newbie, I see the list of stabilized APIs I never encountered. I just have to click on them to get a comprehensive and well written documentation, with links to all the concepts it speaks about.

That is really the sort of documentation I love, the one that are not just boring references but also learning you things. It’s really a great work.

It remembers me that, while I never had the chance to work with Django, more than ten years ago, its documentation literally taught me about how web applications, the concepts, the paradigms, and this probably is the root of my today career.

The people behind this documentation effort really deserve kudos.


As someone who is known for Rust docs, and posts here, I have to say: this is 100% the libs team's effort for keeping this stuff going. I had nothing to do with writing these. Each team is responsible for their own docs these days, and I'm glad that we created a pro-documentation culture early on. Lots of folks doing lots of great work around docs these days.


IIRC, you are one of the authors of The Rust Book, which made me love learning Rust. You did a great job :)


I am! Thank you!


I have been hoping for a while that rust would make some progress toward better supporting setjmp/longjump from C:

https://github.com/rust-lang/rfcs/issues/2625

It's asking a lot, but it's one of very few weak points in Rust/C interoperability, and it would be great if it were addressed.

Of course, this would obviously be marked as unsafe code, and could only be used in very limited ways. But it would still be very useful for my project here:

https://github.com/jeff-davis/postgres-extension.rs

Which has code that handles setjmp/longjmp, and as far as I can tell it produces correct assembly, but it's currently undefined behavior as far as rust is concerned.

There's some related work here:

https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html

But it also seems to have slowed down.


The way you'd want to do this currently would be to catch longjmps on the c side, return an error code, and then begin an unwind on the rust side, catch that, and convert back into a longjmps.

But I agree that it's unfortunate that rust doesn't have good support for C++ exceptions unwinding through rust code.


That's not very practical for what I'm trying to do. A Postgres extension can access a very wide range of internal functions (hundreds), and most of them have the potential to ERROR (longjmp).

These functions are of all different kinds with different numbers and types of arguments, so I'd need to wrap each one, or would need some pretty clever macros or code gen. Rust has really powerful macros (which I'm using currently), and I don't think it would work out as well in C. Also, it means a lot of symbol bloat, because each of these new C functions needs a symbol.

Also, it would mean that my crate would no longer be pure rust, so I'd have to figure out how to build all this C code on whatever platforms.


I see what you mean. That's too bad. I definitely hope there's better support for what you're asking in the future.


Yeah, I mean, I know I'm asking for a lot. No other language comes close to rust as far as C interop, except C++.

And rust is actually better at C interop than C++ in some important ways!

* Rust doesn't mess with struct definitions if they are declared #[repr(C)]. No extra vtable pointers. That means you can pass a struct back and forth between C and rust, and in the rust code you can do dynamic dispatch on that same C struct (no copying/conversion). That's amazing!

* Rust defines Option<&Foo> in a #[repr(C)] struct to be a plain pointer, where NULL means None. That means you can get type safety in rust working with nullable pointers you get from C, to make sure that your rust code checks for None. Again, no conversion or copying, you get this with ordinary nullable pointers coming from C.


Back when I was working on wasm runtimes, I ran into the issue of unwinding an exception through generated code. I had to do something reminiscent of what I mentioned above.


In summary:

> The most significant change in this release is not to the language or standard libraries, but rather an enhancement to tooling support for Clippy.

The following methods were stabilized.

   Arguments::as_str
   Peekable::next_if_eq
   Peekable::next_if
   char::MAX
   char::REPLACEMENT_CHARACTER
   char::UNICODE_VERSION
   char::decode_utf16
   char::from_digit
   char::from_u32_unchecked
   char::from_u32
   slice::partition_point
   str::rsplit_once
   str::split_once
The following previously stable APIs are now const.

   char::len_utf8
   char::len_utf16
   char::to_ascii_uppercase
   char::to_ascii_lowercase
   char::eq_ignore_ascii_case
   u8::to_ascii_uppercase
   u8::to_ascii_lowercase
   u8::eq_ignore_ascii_case
There you go. Enjoy!


> an enhancement to tooling support for Clippy

All we need now is better speech recognition for BonziBuddy.


BonziBuddy ... oh boy! you took me to early 2000s. I remember it installing out of a CD shipped with a IT magazine.


When people complain that rust is changing too fast, I point them to updates like this.


I don’t know why this was downvoted! It’s a great point. I love releases like this.


There are a lot of people on HN who hate rust for whatever reason.


I don't hate rust, but I think I get where they are coming from. The hype to results ratio of rust is off the charts, possibly higher than any language I've ever seen. This makes sense seeing as how a safer C both sounds amazing and also is incredibly hard to pull off apparently, but I can see where this is grating to the casual observer.


I like how easy it is to update rust. Don't have to deal with homebrew or any package managers. Just install once and then run rustup update stable


A smaller release. The most notable thing is probably the update to LLVM 12.

One things I wonder about is why newly stabilized functions like char::from_u32 aren't const fn from the start. I get when existing functions have to be made const after the fact, but to me it feels that new functions should be stabilized already as const unless there is a good reason they can't be (e.g. they allocate).


I don’t know the specifics of this function yet but don’t forget there are lots of things that could be done in const fn that aren’t accepted yet; it’s often the reason things work out like this for these functions.

EDIT: okay, I looked into it! (rust-analyzer is really useful for this...)

this function calls TryFrom::try_from. which runs afoul of https://github.com/rust-lang/rfcs/blob/master/text/0911-cons...

> Traits, trait implementations and their methods cannot be const - this allows us to properly design a constness/CTFE system that interacts well with traits - for more details, see Alternatives.

So, there you go.


Often, functions call trait methods internally and const traits aren't ready for prime time yet iirc.


Mhh you are right. Apparently it calls try_from internally. It throws away the error but often creating errors also allocates.


I wonder if the validation of the char is non-trivial and unwanted at compile time?


Validating should be pretty trivial. Explicitly handling all cases would look something like this:

    #[inline]
    const fn is_valid_scalar(c: u32) -> bool {
        match c {
            0..=0xD7FF => true,
            0xD800..=0xDFFF => false, // surrogate pairs
            0xE000..=0x10FFFF => true,
            0x110000..=u32::MAX => false, // outside of Unicode range
        }
    }
But this could be reduced down to a simple if statement that tests for the invalid ranges.


If you absolutely want to golf it into one line:

  #[inline]
  const fn is_valid_scalar(c: u32) -> bool {
    matches!(c, 0..=0xD7FF) || matches!(c, 0xDE00..=0x10FFFF)
  }
But I prefer your version for its clarity. It should compile into the same thing regardless.


It would be nice if rust could support multiple heaps and tracking their memory usage.

If you are working with a lot of data, you need to use some kind of hybrid cache-friendly memory/disk algorithm. For instance, to find the exact number of unique values, you might choose a hashing approach. If the hash table grows large and starts swapping, that will be incredibly slow. Instead, it's better to limit the hash table to a certain memory footprint, and when it grows any larger, you partition any new unique values you find and write them to disk. Then, you just count the members of the hash table, save the count, throw the hash table away, and read one of the partitions. Repeat until all the partitions are gone.

That requires a few important capabilities:

1. Track the memory usage of the hash table. It might be easy to estimate in simple cases, but when you have variable-width types that have their own pointers, etc., it gets very messy. It would be nice to just deep copy values into the hash table's memory pool, and then ask how big the memory pool is now. If it's over the limit, don't accept new unique values, just send them to the disk partitions.

2. Free the heap all at once and release all the memory when you are done with the current batch.

These things are not easy in C, but straightforward if you have a custom allocator that uses its own regions of memory. But in rust, it's pretty hard to do this in a generic way.


Rust has custom allocators on the way. They're in nightly currently.

You can already set a custom global allocator, but soon you'll be able to specify allocators per collection.


Great! Do you have some links?

I found this: https://doc.rust-lang.org/std/alloc/trait.Allocator.html

but it doesn't look like it allows inspecting the size. I'd also like to know how it works to "move a value in" to a collection, does it actually do a memcpy into the collection's heap?

Also, is it really a separate instance of the allocator for the collection? That is, can I wipe all the memory for one hash table in O(1) without touching another hash table that uses the same allocator?

EDIT: It would also be nice if there was a way to gracefully handle OOM. Maybe if you could specify a maximum size for some heap, it could be a good way to test how your code fails on OOM (which can still happen in a lot of cases with some kernel configs).


Yeah, you'll have to add a method to whatever type you implement `Allocator` for that returns the size.

When you call `Vec::push` or `HashMap::insert`, it'll allocate on the heap if there isn't already capacity for it in the already allocated space. If the custom allocator you make just allocates one large space from the global allocator, then you can deallocate the whole thing at once in the `Drop` implementation.

There is limited documentation at the moment because the feature is still in flux, but take a look at `Vec::new_in` [0] to get an idea of how a collection can use an allocator.

[0]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.new...


(These APIs return Result, so an OOM would give an AllocError back)


Kudos to Tshepang Lekhonkhobe! It’s wonderful to see an African name in the contributors list. Can anyone spot others?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: