News for hackers. Stuff that matters.
Re:Rust 1.25 released by kibwen on Thursday March 29, 2018 @03:59AM (#16705338)
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.)

Re:Rust 1.25 released by pedrocr on Thursday March 29, 2018 @08:50AM (#16706549)
>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.

[1] https://github.com/pedrocr/rawloader/

Re:Rust 1.25 released by cies on Thursday March 29, 2018 @05:57AM (#16705791)
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).
Re:Rust 1.25 released by simias on Thursday March 29, 2018 @06:02AM (#16705811)
>stable SIMD library support

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!

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @06:09AM (#16705847)
You can check it out in nightly here https://doc.rust-lang.org/nightly/std/arch/

> Now I'll have to complain about lack of stable inline ASM support instead!

This one is much, much harder.

Re:Rust 1.25 released by simias on Thursday March 29, 2018 @07:42AM (#16706171)
>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?

Re:Rust 1.25 released by burntsushi on Thursday March 29, 2018 @07:55AM (#16706233)
w.r.t. to SIMD, there are two prongs 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. :-)

[1] - https://github.com/rust-lang/rust/issues/29722

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @09:14AM (#16706695)
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...
Re:Rust 1.25 released by simias on Thursday March 29, 2018 @09:14AM (#16706686)
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...
Re:Rust 1.25 released by hsivonen on Thursday March 29, 2018 @08:50AM (#16706550)
> You can check it out in nightly here https://doc.rust-lang.org/nightly/std/arch/

https://doc.rust-lang.org/nightly/std/simd/ deserves mention, too, because it leapfrogs C and C++ (whereas std::arch brings Rust to parity).

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @09:13AM (#16706684)
Yes, that's not being stabilized soon though, and is much more experimental.
Re:Rust 1.25 released by mathw on Thursday March 29, 2018 @08:11AM (#16706309)
Every release that doesn't have impl Trait is a bit of a disappointment, but I appreciate it has to be done right.

So excited for that one single improvement, it's going to make many things so much easier. Especially working with Futures and Iterators.

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @09:19AM (#16706741)
Well, you've got six weeks to wait :)
Re:Rust 1.25 released by mathw on Thursday March 29, 2018 @09:25AM (#16706795)
It's in 1.26??

YES!

YES!

WOOOOO!!!

That's basically my birthday present.

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @09:36AM (#16706885)
Yup! In both argument and return positions; in trait methods isn't in yet.

1.26 and 1.27 are gonna be really big, I wasn't kidding :)

Re:Rust 1.25 released by mathw on Thursday March 29, 2018 @01:53PM (#16709272)
Both positions! Woooo!

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.

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @01:59PM (#16709345)
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!
Re:Rust 1.25 released by eslaught on Thursday March 29, 2018 @01:14PM (#16708812)
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.

[1]: https://internals.rust-lang.org/t/rust-release-milestone-pre...

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @01:18PM (#16708863)
Not in general, but for Rust 2018, the edition release, we have https://docs.google.com/spreadsheets/d/188xuIgrzGLCu68UKpRjc... (note the tabs too)

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)

Re:Rust 1.25 released by mrec on Thursday March 29, 2018 @07:44AM (#16706184)
> It'll be great to finally be able to experiment with LLD.

Was the lack of lld the only reason for the Windows installer to depend on the MSVC build tools, or are there others?

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @09:19AM (#16706739)
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!

Re:Rust 1.25 released by mrec on Thursday March 29, 2018 @11:08AM (#16707641)
> If you want to compile C code to include in your project, you'll need those tools.

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.

Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @11:15AM (#16707701)
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.

Re:Rust 1.25 released by mrec on Thursday March 29, 2018 @12:04PM (#16708128)
Ah, gotcha. Thanks for clarifying.
Re:Rust 1.25 released by Buttons840 on Thursday March 29, 2018 @11:00AM (#16707590)
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?
Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @11:13AM (#16707672)
Consider this code:

  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".
Re:Rust 1.25 released by mike-cardwell on Thursday March 29, 2018 @02:11PM (#16709473)
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.
Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @03:02PM (#16710084)
okay so, the un-elided version of foo_no is

  fn foo_no<'a>(v: &'a [i32]) -> std::iter::Cloned<std::slice::Iter<'a, i32>> {
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.
Re:Rust 1.25 released by mike-cardwell on Thursday March 29, 2018 @03:13PM (#16710173)
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?
Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @03:51PM (#16710481)
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?
Re:Rust 1.25 released by mike-cardwell on Thursday March 29, 2018 @04:27PM (#16710746)
Yes. Thanks for the explanation.
Re:Rust 1.25 released by irishsultan on Thursday March 29, 2018 @04:30PM (#16710771)
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.
Re:Rust 1.25 released by Buttons840 on Thursday March 29, 2018 @01:11PM (#16708779)
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.
Re:Rust 1.25 released by steveklabnik on Thursday March 29, 2018 @01:15PM (#16708830)
No problem! It also does enable some other things too. For example, closures have a type that's not writable, so

  fn foo() -> impl Fn(i32) -> i32 {
      |x| x + 1
  }
can be written, since closures implement the Fn trait, but there's no way to write the type directly.