The big thing in this one is the LLVM upgrade, which has been a long time coming. :) We actually skipped LLVM 5 entirely due to some issues with emscripten. It'll be great to finally be able to experiment with LLD.
Looking forward, the next two releases, 1.26 and 1.27, are going to have some major features that we've been working on for a long, long time, such as "impl trait" (which should allow for improved performance, simpler syntax for the typical use of generics, and greatly improve error messages for extensive use of generics), more ergonomic matching when dealing with references, 128-bit integers, stable SIMD library support, and others. This whole year is going to see the continued stabilization of the ergonomics intiatives from last year, so stay tuned for lots of welcome tweaks to make Rust easier to write and read. :)
(I should also mention that this release happened live from the Rust All-Hands happening in Berlin, which has been a massively productive time so far; keep an eye out for the eventual workweek recap which will hopefully enumerate the tons of improvements (e.g. reducing Rust binary sizes by 10%) and future initiatives (e.g. forming an official Verification Team) that have happened this week.)
I love this focus on ergonomics in the Rust community. Recently I had to work with a Rust code base and I was amazed by how clean the tooling is compared to other low-level language stacks (C, C++ basically).
Oh, that's a huge one for me and I didn't even know it was in the pipeline, very happy to hear that. Now I'll have to complain about lack of stable inline ASM support instead!
I'm curious why that is, intuitively I'd have assumed that SIMD support would be trickier to stabilize (since you need a generic interface over a wide range of implementations) while inline ASM is pretty much "just copy-paste this bit of assembly in the middle of this function" which I assume is already something LLVM can do easily since it needs that for C/C++. Since nobody expects inline ASM to be portable you don't have to worry about making one single generic interface to it.
* Platform dependent functions that match an upstream vendor's API. (Think __m128i and friends.)
* Platform independent APIs that provide portable vector APIs.
The former is necessary because the latter cannot ever hope to cover all use cases supported by CPUs. The latter is necessary because it can hit many use cases, and finding the optimal implementation for every operation for every permutation of platform (and every permutation of CPU feature on each platform) is a non-trivial task.
So yeah, that is indeed a ton of work. However, LLVM does a lot of the heavy lifting for us, particularly with respect to the implementation of the portable API. "All" we have to do is define an API we're willing to stabilize in `std`. (Which is no easy task.)
I'm less in touch with the inline ASM feature, but like most things, I expect it is much more complex than you're suggesting. You can read more about it on the tracking issue for inline ASM[1]. Remember, if we're stabilizing something, then we need to make sure it continues to work. If LLVM's doesn't uphold that guarantee, that we must necessarily provide our own interface that is stable. "Just expose LLVM's internals" is not really an acceptable answer, and it was in fact a large part of the SIMD effort (building APIs we can stabilize on top of what LLVM supports).
I'd also like to note that the stabilization of the former piece above (platform dependent vendor intrinsics) eats into many of the use cases for inline ASM. Not all of course, but many. :-)
Very insightful, thank you. Reading through the github discussion I'm also glad to see that there seems to be a consensus for not adopting gcc's atrocious inline ASM syntax...
Yes, the fact that we basically just do what LLVM does, and that that's not stable, is a huge blocker. There's also the broader question of "DSL" vs the way that LLVM does it...
There are others. If you want to compile C code to include in your project, you'll need those tools. LLD and link.exe aren't exactly at feature parity, etc.
I'm most excited about LLD for hobby OS dev; with Rust and LLD it's now trivial to get going on any OS Rust supports. As a Windows user, I really appreciate it!
That works if you can actually compile the code yourself, I left out the "if you want to link to a pre-compiled library that was compiled with MSVC" case.
Basically, MSVC is the default, standard way to access C code on the platform, so we work with it by default. We also provide other options if you want to do it other ways, through things like the GNU target.
Is anyone keeping something like [1] up-to-date? It's nice to able to see what's coming up in the next releases, for those of us who don't follow Rust closely enough to navigate the issue soup.
It is, of course, best-effort, and often guestimates, so please don't take it as gospel, but describes what we're trying to do. (There was already one situation where a mistake in the spreadsheet caused someone to be misled about when a feature is going to be available)
Trait methods, eh, we'll just have to live without that for now, just making it easy to return iterator chains from functions is a massive thing for me and a huge boost to the usability of the language and the practical value of trait abstractions.
But you know that, of course. I'm just excited.
Now very interested in what 1.27 will have in it! I haven't tripped over the lack of NLL for a while, but that's been another thing I've been eagerly awaiting because I used to and I've just trained myself out of it.
Again, I gotta repeat: this is not a promise. Development on 1.26 is just starting, so this is a reasonably far out estimate, and might be wrong.
But with that said... some possible features:
* dyn Trait
* unit tests that can use ?
But, looking at the tracking sheet I linked below, it's looking like 1.26 and 1.29 are gonna be the biggies, some 1.27 stuff is pushed back a bit. We'll see!
>The big thing in this one is the LLVM upgrade, which has been a long time coming.
This is great news. I just ran my usual benchmark and it seems a performance regression has been fixed and some performance added over that. I'm measuring the speed of loading a Sony A77 raw file in rawloader[1]. That includes TIFF parsing and then a tight loop that processes every pixel. Here's the version history:
1.17 - 95ms
1.18 - 80ms (-16%)
1.19 - 79ms (-16%)
1.20 - 80ms (-16%)
1.21 - 79ms (-17%)
1.22 - 79ms (-17%)
1.23 - 79ms (-17%)
1.24 - 84ms (-12%)
1.25 - 74ms (-22%)
I believe the jump in 1.18 was LLVM 4.0 and now LLVM 6.0 is giving me a new performance jump. No idea what happened in 1.24 though but it seems to be fixed now.
I'm out of the loop. How will "impl Trait" help with errors? Does it automatically improve errors, or just allow library authors to implement custom error or something?
fn foo_no(v: &[i32]) -> std::iter::Cloned<std::slice::Iter<i32>> {
v.iter().cloned()
}
fn foo_impl<'a>(v: &'a [i32]) -> impl Iterator<Item=i32> + 'a {
v.iter().cloned()
}
fn main() {
let v = vec![1, 2, 3];
let () = foo_no(&v);
let () = foo_impl(&v);
}
Given the let ()s, this will fail to compile for both. For the first, you get
= note: expected type `std::iter::Cloned<std::slice::Iter<'_, i32>>`
for the second, you get
= note: expected type `impl std::iter::Iterator`
The former gets longer and longer based on how many iterator chains you do, the latter will be the same no matter how many you add. It's also just generally way more clear, "I was expecting something implementing Iterator, and I didn't get it" vs "I was expecting this exact chain of nested iterators".
Ok. It looks like the new feature allows library authors to express their intentions with simpler code, and thus error messages will also be simpler. Looks good, thanks for taking the time to answer my question.
Can you explain why an explicit lifetime is needed in foo_impl? I don't see a connection between the function argument lifetime and the return value lifetime, as the return value is a brand new object with cloned values... I realise I'm missing something fundamental here.
I am not sure why the impl Trait version doesn't elide properly; I wrote it without the lifetime first and the compiler told me I need it, so I wrote it out, which is often what happens to me in these situations. I assume, since the elision rules were written years before impl Trait became a thing, that there's some sort of reason why it doesn't elide, but honestly, I'm not sure.
So why is the lifetime of the return value linked to the lifetime of the function argument? Couldn't the return value live longer than the function argument in that example?
In both cases, the iterators are over the slice, so their lifetimes need to be tied together. The iterator can't live longer than the slice, or it'd be a use after free. Does that make sense?
The Cloned iterator clones the elements of the underlying iterator, but only on-demand, so obviously it can't do that once the argument isn't live anymore.
If you want to get something done with microcontrollers, ARM Cortex-M tends to be much more powerful and is already great fun to write Rust for. It's a bit of work to get started--certainly a lot compared to Arduino which abstracts away even things that shouldn't be--but the code can be much more readable and portable than the corresponding C.
Nested import groups will often be uglier, but there are definitely some cases where they lead to much prettier code with no loss of obviousness, and nesting was a logical extension (in a “why don’t we have this?” kind of way, in my opinion) of import grouping, making that feature more internally consistent.
There is a lot of activity around async/await. My understanding is that the hard work is nearly done, and what is left is mostly around the final syntax. I think its planned the land in stable with the Rust 2018 edition (https://blog.rust-lang.org/2018/03/12/roadmap.html) or shortly after it.
There's sorta two possibilities here; the procedural macro based version and some sort of native keyword version. We don't have a target release number yet, but sometime in the first three quarters of the year is a vague sort of target.
The networking WG just started literally today, and will be shepherding the work. I'm not yet sure where the best tracking issue is; if I find out soon I'll leave another comment.
For whatever my two cents are worth, I would choose a macro over a keyword every day. Keyword clutter can be incredibly stifling once a language has any history at all.
This llvm should have newgvn which allows better auto vectorization. I'm curious to see if panic=abort allows some of the nbody implementations at benchmark game to autovec. Might not have to wait on SIMD to beat c++. The fastest nobody entry is FORTRAN and it has no intrinsics, just autovec.
> cargo doc, ... . It’s getting a huge speed boost in this release, as now, it uses cargo check, rather than a full cargo build
This is great. I often run cargo doc after adding new library dependencies or even for my own new interfaces to be able to click through the code. This is a wonderful tool, especially while IDEs are still coming up to speed.
Are IDEs using cargo doc? or are they reimplementing the markdown processing?
My understanding is that they use their own markdown processing, but I'm not actually sure. The RLS presents the raw text as far as I know; I'm not sure how the IntelliJ stuff works.
54 comments
[ 1.6 ms ] story [ 109 ms ] thread(we had some issues with GH pages)
Looking forward, the next two releases, 1.26 and 1.27, are going to have some major features that we've been working on for a long, long time, such as "impl trait" (which should allow for improved performance, simpler syntax for the typical use of generics, and greatly improve error messages for extensive use of generics), more ergonomic matching when dealing with references, 128-bit integers, stable SIMD library support, and others. This whole year is going to see the continued stabilization of the ergonomics intiatives from last year, so stay tuned for lots of welcome tweaks to make Rust easier to write and read. :)
(I should also mention that this release happened live from the Rust All-Hands happening in Berlin, which has been a massively productive time so far; keep an eye out for the eventual workweek recap which will hopefully enumerate the tons of improvements (e.g. reducing Rust binary sizes by 10%) and future initiatives (e.g. forming an official Verification Team) that have happened this week.)
Oh, that's a huge one for me and I didn't even know it was in the pipeline, very happy to hear that. Now I'll have to complain about lack of stable inline ASM support instead!
> Now I'll have to complain about lack of stable inline ASM support instead!
This one is much, much harder.
I'm curious why that is, intuitively I'd have assumed that SIMD support would be trickier to stabilize (since you need a generic interface over a wide range of implementations) while inline ASM is pretty much "just copy-paste this bit of assembly in the middle of this function" which I assume is already something LLVM can do easily since it needs that for C/C++. Since nobody expects inline ASM to be portable you don't have to worry about making one single generic interface to it.
What's the catch?
* Platform dependent functions that match an upstream vendor's API. (Think __m128i and friends.)
* Platform independent APIs that provide portable vector APIs.
The former is necessary because the latter cannot ever hope to cover all use cases supported by CPUs. The latter is necessary because it can hit many use cases, and finding the optimal implementation for every operation for every permutation of platform (and every permutation of CPU feature on each platform) is a non-trivial task.
So yeah, that is indeed a ton of work. However, LLVM does a lot of the heavy lifting for us, particularly with respect to the implementation of the portable API. "All" we have to do is define an API we're willing to stabilize in `std`. (Which is no easy task.)
I'm less in touch with the inline ASM feature, but like most things, I expect it is much more complex than you're suggesting. You can read more about it on the tracking issue for inline ASM[1]. Remember, if we're stabilizing something, then we need to make sure it continues to work. If LLVM's doesn't uphold that guarantee, that we must necessarily provide our own interface that is stable. "Just expose LLVM's internals" is not really an acceptable answer, and it was in fact a large part of the SIMD effort (building APIs we can stabilize on top of what LLVM supports).
I'd also like to note that the stabilization of the former piece above (platform dependent vendor intrinsics) eats into many of the use cases for inline ASM. Not all of course, but many. :-)
[1] - https://github.com/rust-lang/rust/issues/29722
https://doc.rust-lang.org/nightly/std/simd/ deserves mention, too, because it leapfrogs C and C++ (whereas std::arch brings Rust to parity).
Was the lack of lld the only reason for the Windows installer to depend on the MSVC build tools, or are there others?
I'm most excited about LLD for hobby OS dev; with Rust and LLD it's now trivial to get going on any OS Rust supports. As a Windows user, I really appreciate it!
Just curious, but if you're already built on top of llvm, why not bundle clang for that? Licensing issues? I thought NCSA was pretty permissive.
Basically, MSVC is the default, standard way to access C code on the platform, so we work with it by default. We also provide other options if you want to do it other ways, through things like the GNU target.
So excited for that one single improvement, it's going to make many things so much easier. Especially working with Futures and Iterators.
YES!
YES!
WOOOOO!!!
That's basically my birthday present.
1.26 and 1.27 are gonna be really big, I wasn't kidding :)
[1]: https://internals.rust-lang.org/t/rust-release-milestone-pre...
It is, of course, best-effort, and often guestimates, so please don't take it as gospel, but describes what we're trying to do. (There was already one situation where a mistake in the spreadsheet caused someone to be misled about when a feature is going to be available)
Trait methods, eh, we'll just have to live without that for now, just making it easy to return iterator chains from functions is a massive thing for me and a huge boost to the usability of the language and the practical value of trait abstractions.
But you know that, of course. I'm just excited.
Now very interested in what 1.27 will have in it! I haven't tripped over the lack of NLL for a while, but that's been another thing I've been eagerly awaiting because I used to and I've just trained myself out of it.
But with that said... some possible features:
But, looking at the tracking sheet I linked below, it's looking like 1.26 and 1.29 are gonna be the biggies, some 1.27 stuff is pushed back a bit. We'll see!This is great news. I just ran my usual benchmark and it seems a performance regression has been fixed and some performance added over that. I'm measuring the speed of loading a Sony A77 raw file in rawloader[1]. That includes TIFF parsing and then a tight loop that processes every pixel. Here's the version history:
1.17 - 95ms
1.18 - 80ms (-16%)
1.19 - 79ms (-16%)
1.20 - 80ms (-16%)
1.21 - 79ms (-17%)
1.22 - 79ms (-17%)
1.23 - 79ms (-17%)
1.24 - 84ms (-12%)
1.25 - 74ms (-22%)
I believe the jump in 1.18 was LLVM 4.0 and now LLVM 6.0 is giving me a new performance jump. No idea what happened in 1.24 though but it seems to be fixed now.
[1] https://github.com/pedrocr/rawloader/
Because if so I have an amazing excuse to finally learn rust
For example, get this $2 board http://wiki.stm32duino.com/index.php?title=Blue_Pill and use this library (see the examples!) https://github.com/japaric/stm32f103xx-hal
There probably will eventually be AVR implementations of https://github.com/japaric/embedded-hal so you could run mostly the same code on an Arduino board.
man, they work really hard to keep their language ugly & confusing
There is a recent blog series tracking the quite exciting progress being made at the moment (part vi, latest in the series): https://boats.gitlab.io/blog/post/2018-03-20-async-vi/
There is an experimental RFC tracking generators with an initial syntax design: https://github.com/rust-lang/rfcs/blob/master/text/2033-expe...
The networking WG just started literally today, and will be shepherding the work. I'm not yet sure where the best tracking issue is; if I find out soon I'll leave another comment.
This is great. I often run cargo doc after adding new library dependencies or even for my own new interfaces to be able to click through the code. This is a wonderful tool, especially while IDEs are still coming up to speed.
Are IDEs using cargo doc? or are they reimplementing the markdown processing?