
Announcing Rust 1.9 - steveklabnik
http://blog.rust-lang.org/2016/05/26/Rust-1.9.html
======
asp2insp
_The time complexity of comparing variables for equivalence during type
unification is reduced from O(n!) to O(n). As a result, some programming
patterns compile much, much more quickly._

I love this. Not just my code compiling more quickly, but the underlying
implementation is super interesting.

~~~
kvark
Is this something seen frequently in user code, or just an edge case? I'd love
to get even faster with my libraries compiling, but honestly the continuous
improvements in compile speed over the last half a year have already made me
happy :)

~~~
topspin
Indeed. It's hard to miss just how much better rustc performance has become
recently. As I've watched this I been left wondering; is it just the blood and
sweat of the compiler developers doing this or is the language somehow
inherently efficient to compile? I know there are other, much older languages
that seem unable to deal with their compiler performance problems.

~~~
steveklabnik
It is a combination of both. We took performance into consideration when
designing all aspects of the langauge, and so we've laid a lot of groundwork.
The gains have come because the compiler had so much technical debt; imagine a
hundreds of thousands of LOC codebase where the language changes out from
under it on a weekly/daily basis. So every since 1.0, and even before, really,
it's been paying off debt, and doing things in better ways. And there's more
coming. Incremental recompilation will make after-the-first compiles go even
faster. But all of that takes tons of work.

~~~
Gankro
On the other hand, niko has described trait resolution as "basically prolog",
so that's something you can push to perform as degenerately bad as you want
(the recent addition of specialization only making things worse).

The issue is just how degenerately bad "most" code is -- and I think that
hinges a lot on how excited the word "higher" gets you vis-a-vis expressing
your programs. If you think C# is a pretty cool type system that doesn't
afraid of anything you'll probably be fine. If you think scala or haskell with
All The GHC Extensions is where it's at... watch out.

~~~
tatterdemalion
> I think that hinges a lot on how excited the word "higher" gets you vis-a-
> vis expressing your programs.

You are the best Gankro. <3

What's nice about coherence is that there's little risk in modifying the
constraint solving algorithm to optimize for the common use cases (because it
can't be backward incompatible). What's nice about crater is that it's
comparatively easy to test that optimization.

------
jeffdavis
Excited about unwinding becoming stable. I am hacking on postgres-
extension.rs, which allows writing postgres extensions in rust. This will mean
that postgres could call into rust code, then rust could call back into
postgres code, and that postgres code could throw an error, and rust could
safely unwind and re-throw. Cool!!

~~~
sbuttgereit
Very much pleased to see you working on this. I've been thinking that Rust
would make an excellent language for those of us that want to get a bit closer
to C-like backed functions and such, but aren't really C programmers. While
Rust has it's own learning curve to be sure and isn't magic, the compiler can
save those of us familiar with less systemy languages from mistakes we
wouldn't otherwise be sensitive to.

~~~
jeffdavis
By "hacking on" I mean "submitted a pull request to Daniel Fagnan's project".
I didn't mean to take credit.

But I do plan to keep improving it.

------
shmerl
Progress on specialization is good.

 _> Altogether, this relatively small extension to the trait system yields
benefits for performance and code reuse, and it lays the groundwork for an
"efficient inheritance" scheme that is largely based on the trait system_

------
bryanray
Looks like a great release. Controlled unwinding looks very interesting.
#GreatJobRustTeam

------
MichaelGG
I don't understand the announcement on panics. Hasn't it always been the case
that thread boundaries (via spawn) could contain panics?

It's also used to have the incorrect default that such panics were silently
ignored. .NET made this same mistake: background threads could silently die.
They reversed and made a breaking change so any uncaught exception kills the
process. I'd imagine Rust will do so by encouraging a different API if they
haven't already. (I opened an RFC on this last year, but I didn't understand
enough Rust and made a mess of it. But still a great experience, speaking to
the very kind and professional community. In particular several people were
patient, but firm, in explaining my misunderstandings.)

~~~
steveklabnik

      > Hasn't it always been the case that thread boundaries (via spawn)
      > could contain panics?
    

Yes. This lets you catch an unwinding panic from inside the thread itself,
rather than observing it get killed from the outside.

In Rust, they're not silently ignored: `join()` returns a `Result`, which has
a `must_use` attribute, which will warn if you don't do something with it.

~~~
MichaelGG
Thanks for the clarification.

On thread panics: Suppose you have a long-running thread that's updating
shared variable. You don't call join on it; just drop it, so it's detached,
running in the background. If that thread crashes (and isn't in e.g. a mutex
so it can't poison), your process will continue on in an invalid state. Yes,
you could add code to notice the panic and abort the process, but by default,
it'll silently fail, right?

~~~
steveklabnik

      > and isn't in eg a mutex so it can't poison
    

Well, Rust makes sure that you have _some_ kind of concurrency primitive in
place to make this safe.

It's also worth mentioning that Rust is concerned about preventing memory
safety bugs, not every single kind of bug ever. I mean, we want to encourage
robust code, but we don't make the claim that Rust solves every kind of bug
possible with the type system.

~~~
MichaelGG
I understand. It just seems like a very odd default, allowing threads to
silently crash. Is there ever a good scenario for this? Flip it around: if the
default was thread crash->panic, would any users be upset? Are there people
_intentionally_ depending on silent panics?

It is the opposite of robust, more toward "on error resume next", to be rude.
Just feels like an odd choice, that's all.

Edit: As an example: Suppose a background thread opens a file and writes out
its pid and date every minute. If there's any panic on that thread, then the
process will just go on, oblivious to the error. I find it hard to believe
that's remotely close to the majority of intentions when spawning a detached
background thread. For the few cases when you want "fire-and-forget-and-
don't-care-if-it-fails", explicitly stating so seems wise.

~~~
steveklabnik
Yes, one of the reasons that catching panics was even stabilized in the first
place is because in many scenarios, aborts are not acceptable. Embedding Rust
in other languages and runtimes is an important use case, for example, and a
bug in your Rust extension bringing down your whole Rails app is not great.

The idea is not to make panics silent, but to be able to go from "this process
is crashing" to "here's an error code".

~~~
ori_b
> Embedding Rust in other languages and runtimes is an important use case, for
> example, and a bug in your Rust extension bringing down your whole Rails app
> is not great.

It's not, but it beats it silently ending up in a bad state.

~~~
kibwen
The failure case in mind here is not silent data corruption, it is merely
having your in-process performance monitoring service go offline.

------
JoshTriplett
I'm really looking forward to the next stable version after this, which will
hopefully stabilize the new '?' syntax for 'try!'.

~~~
steveklabnik
I can guarantee you it will not. ? is still unstable, and since the release of
1.9 means that 1.10 is in beta, it will not be in 1.10.

~~~
JoshTriplett
What's the remaining work needed to make '?' no longer unstable?

~~~
steveklabnik
Well for one, there's a huuuuuge unresolved question: should it work for
Option as well as Result? If we stabilized just the Result version, would we
lock out the possibility of extending it in the future?

Just in general, it is a huge, and widely debated new feature that only landed
recently. It needs more time before we can consider stabilizing it. One of the
longest-running and most-commented RFCs in Rust history deserves to not just
be made stable as quickly as possible, but to take it slow and make sure we
get it right.

~~~
JoshTriplett
I've read the RFC and quite a bit of the surrounding debate, and I knew that
most of it would take longer to stabilize. I just didn't realize that the '?'
notation in particular was still under debate.

Why would stabilizing the Result version of '?' lock out the possibility of
supporting it on Option or other types in the future?

In any case, I look forward to it whenever it becomes available in a stable
release.

~~~
steveklabnik

      > Why would stabilizing the Result version
    

Well, because in stabilizing something, you have to declare exactly what is
stable, and what the semantics are. "? only works with Result" is not a
detailed enough semantic, so you have to dig into details. Is it based on a
trait? If so, and the trait gets designed incorrectly, it could cause
problems. Is it not based on a trait? Now the language needs to know about
Result, specifically.

    
    
      > I just didn't realize that the '?' notation in particular was still under debate.
    
    

Well, we have never had a case yet where an accepted RFC failed to end up
actually being stable. We have had some RFCs that have had final details take
a very long time. But in theory, it could happen.

~~~
Gankro
Uh... That doesn't seem true at all? Unstable stuff gets deprecated all the
time (the libs team basically _defaults_ to delete-everything), and I assure
you that some of that stuff was accepted in an RFC. There's also the case that
the design is significantly changed in inplementation or as an ammendment RFC
(e.g. maybe ? becomes ?? or ?! to let ? be used like swift/c#). Entry API is
the most obvious case of this kind of change happening to me. BTree range api
will literally never be stabilized as-is. The defaults-affect-inference design
has been dead in the water for months, for an example from the lang team.

~~~
steveklabnik
So, when I think about this, all the stuff that was unstable and therefore
deprecated landed pre 1.0, but I _guess_ that was still RFC'd? Maybe my
timeline is a bit off here.

I guess, my ultimate point is this: we have not made very many significant
language changes in this first year of Rust. Now, we're starting to. It's new
territory. Things can happen that may not have happened before, including
these significant new features not actually landing.

------
spion
I don't know how this unexpected vs expected errors philosophy gets
propagated, but to me it always looked suspicious. Take array bounds for
example: what if you have an API that lets users send a list of image
transformations, and the user requests a face-detect crop, followed by a fixed
crop with a given x, y, w, h.

Clearly your code can get out of (2D) array bounds with the fixed crop (if the
image is such that the face-detect crop ends up small enough). Suddenly the
thing that was "unexpected" at the array level becomes very much expected at
the higher API level.

So the API provider can't decide whether an error is expected or not. Only the
API consumer can do that. Applying this further, a mid-level consumer cannot
(always) make the decision either. Which is why exceptions work the way they
do: bubble until a consumer makes a decision, otherwise consider the whole
error unexpected. Mid-level consumers should use finally (or even better,
defer!) to clean up any potentially bad state.

I think Swift got this right. What you care about isn't what exactly was
thrown (checked, typed exceptions) but the critical thing is whether a call
throws or not. This informs us whether to use finally/defer to clean up. The
rest of error handling is easy: we handle errors we expect, we fix errors we
forgot to expect, but either way we don't crash for clean up because
finally/defer/destructors take care of that.

~~~
Manishearth
This is why almost every panicky API has a non-panicky variant.

Non-panicky APIs can be used in a panicky way via unwrap() or expect(). There
are _very few_ panicky APIs, reserved for things where 99% of the time you
want it to panic and it would be annoying to have to handle errors all the
time. Array indexing is one of these cases, where it would be super annoying
to handle errors on each indexing operation.

But if you're in a situation where you expect an index to fail, just use
`get()` which returns an Option instead.

APIs do not make the decision for you. At most they decide if the panicky API
is easier to use than the monadic error one. Which is where the fuzzy notion
of "unexpected" and "expected" errors at the API level comes up, it's good
enough to be able to determine what the default should be. Callers still have
the power to do something else.

~~~
dikaiosune
I would kill to have a monadic slicing API for Vec<T>, though. It seems like
the one significant exception to the "use whichever works better for you"
argument. Of course you can bounds check yourself first and return Err if
there's a problem, but there's also no get_unchecked() for slices so you'd pay
for the checks twice.

~~~
Sean1708
> but there's also no get_unchecked() for slices so you'd pay for the checks
> twice.

Yeah there is[1], unless I'm being really stupid...

[1]: [https://doc.rust-
lang.org/std/primitive.slice.html#method.ge...](https://doc.rust-
lang.org/std/primitive.slice.html#method.get_unchecked)

~~~
dikaiosune
Rather, there's no get_unchecked to get a slice from a Vec. Unlike index,
get_unchecked can't take a range as input.

~~~
Sean1708
Ah gotcha, sounds like it could be a good first RFC for someone.

~~~
dikaiosune
I'll add it to my long list of rust projects I wish I had time to do :).

------
wyldfire
_Unexpected problems are bugs: they arise due to a contract or assertion being
violated._

Speaking of which, DBC [1] would be an awesome feature for consideration. It's
one of relatively few areas where D is superior to Rust IMO.

[1] [https://github.com/rust-lang/rfcs/issues/1077](https://github.com/rust-
lang/rfcs/issues/1077)

------
mtgx
Wow, almost 2.0 already. Any major features reserved for 2.0 or will it be
just another typical release like 1.8 or 1.9, more or less?

~~~
Nekit1234007
Next release will most likely be 1.10. As per semver.

------
Animats
_catch_unwind_

Exceptions, at last! Not very good exceptions, though. About at the level of
Go's "recover()". If this is done right, so that locks unlock, destructors
run, and reference counts are updated, it's all the complexity of exceptions
for some of the benefits.

I'd rather have real exceptions than sort-of exceptions.

~~~
vvanders
So much snark.

Error handling is something Rust does really well. Having used exception
languages quite a bit I much prefer the forced handled return values.

Exceptions don't map well to the type of handling patterns like and_then(...),
or_else(...) and the like which I find much more ergonomic and clean.

~~~
valarauca1
Exceptions can also be a pain to deal with in lazy Iterators. Either every
lambda needs to be a try statement, or you need state.

