
Rust 2018 is here, but what is it? - jsheard
https://hacks.mozilla.org/2018/12/rust-2018-is-here?
======
ronjouch
Particularly thunderous applause for providing both backwards compatibility
(published packages will keep working, won't require anything from
maintainers, and we can mix old and new) _and_ autofix features (for when
maintainers are willing to make the breaking changes).

Glad Rust learned from breaking changes hiccups of other programming languages
:)

 _EDIT see discussion with kibwen below: fixed forward compat to backwards._

~~~
kibwen
_> published packages will keep working and won't require anything from
maintainers_

That's backwards compatibility: new versions of the compiler will continue to
be compatible with code that was written previously. Forwards compatibility
would mean that new code would be compatible with old versions of the compiler
(this would be analogous to a website from 2018 working in IE5, or being able
to play The Last Of Us on PS1). Rust's backwards-compatibility promise ensures
the former, but not the latter.

That said, if you stick edition=2015 in your crates, that might go a liiiiitle
bit towards keeping your code compiling on old versions of rustc, allowing you
to partially "opt-in" to forward compatibility for your users, if you so
chose. Though this would only keep you from accidentally using things that are
edition-specific; remember that when you use a version of rustc from here on
out, if you compile with the 2015 edition, you're _not_ just getting a version
of the compiler frozen as of last month; code compiling with the 2015 edition
will still be receiving most of the same features as the 2018 edition (a
strict subset, obviously; they're still the same compiler under the hood, only
the frontmost of the frontend diverges).

~~~
steveklabnik
adding the edition 2015 key will _harm_ your ability to compile on older
rusts, as they don’t understand the edition key. Just leaving it off as the
default is better.

~~~
kibwen
Ah, very good point! I was imagining the case where some does `cargo new`,
which will give them `edition=2018` automatically, and didn't consider that
you could just delete that line rather than editing it. :)

------
pornel
It's a long text, but key takeaways are:

• There are no disruptive changes. You'll just opt in to a couple of new
keywords and some warnings turned into errors (most of which will be fixed for
you automatically). The "old" code continues to work unchanged and can be
mixed with the "new".

• In the last year, in general, Rust has fixed a bunch of papercuts in the
syntax, modules/namespaces, and the borrow checker that were annoying and
unintuitive. New tooling has been added. It's now easier for new users, so if
you've hit a wall with Rust 2015, give Rust 2018 a try.

• Rust is finding its strengths in embedded, WASM, CLI apps, and these areas
are getting more polished.

• High-performance networking is another area of focus, and async/await is
coming soon.

------
nindalf
Lin Clark, the author of this post, is extraordinarily skilled at explaining
complex ideas in layman's terms. Here's another example of their work -
[https://hacks.mozilla.org/2018/10/calls-between-
javascript-a...](https://hacks.mozilla.org/2018/10/calls-between-javascript-
and-webassembly-are-finally-fast-%f0%9f%8e%89/)

~~~
mistahchris
Agreed. Lin Clark has a special skill.

------
dilap
> Using rustfmt ensures that all of your Rust code conforms to the same style,
> like clang format does for C++ and Prettier does for JavaScript.

Oh, and also this obscure little program gofmt ;-)

~~~
steveklabnik
gofmt was certainly a huge inspiration here, and many of us are jealous that
go had it so early in their evolution. Not sure why it wasn't included!

~~~
vanderZwan
Seriously though, the Go core team has been saying from the start that even
they were surprised how big of a positive impact gofmt had. It reduces
bikeshedding _and_ makes it easier for people to read each other's code
because you learn to read the same basic structure fluently and quickly.

It's a basic IxD lesson about software tooling that I think more languages
should pick up on.

Personally, I think I miss gofmt-on-save more than any other feature when I
write other languages (gofmt is a lot more robust than autoformatters in most
other languages). Being able to type carelessly and quickly and know the
output will be corrected as soon as I hit CTRL+S lets me focus on putting my
thoughts on the screen. And it even works as a soft-compiler: if the
autoformatter breaks it means I have a bug somewhere.

~~~
dan_quixote
> It reduces bikeshedding

My team works in equal parts go, ruby and javascript. Code review for go code
is SO much easier. And it's mostly thanks to gofmt. It still amazes me how
fervently some will argue about a single line of white-space or an optional
semi-colon...

------
danieldk
I just converted one smaller crate and it was only about 5 minutes of work
with _cargo fix --edition_. Especially because it does not matter that all the
dependencies are still in Rust 2015.

Besides NLL, I really like the changes in the module system. Having to use
_extern crate_ was a drag, so it's nice that that isn't necessary anymore.
Importing macros with _use_ is both nicer and more intuitive than _macro_use_.

Very well done Rust team!

~~~
Cursuviam
Same here. The only real work I had to do was removing some unnecessary
imports because of the new improvements to mod namespaces.

------
reissbaker
Really excited that non-lexical lifetimes landed! This was the most confusing
part of the borrow checker: NLLs were the main class of "this _should_ work
but it doesn't" that I encountered in Rust. This should make Rust feel easier
to pick up.

------
Waterluvian
This might seem silly but I'm struggling to get into rust because the vscode
plugin for it is sometimes too buggy (but the progress on it is awesome and
devs deserve a round of applause). I use vscode for 4 or 5 other languages
every week and don't want to maintain multiple text editors/IDEs.

What do people usually do in these cases? Surely I'm not alone.

~~~
ahmedalsudani
Why get hung up on one tool? Just write Rust code as if it were plain text.
It's a statically typed language, so the compiler will check your code before
running it, and your can run rust fmt to fix formatting.

Maybe one day you can shun the darkness and embrace emacs ;) all your problems
disappear on that day

~~~
always_good
Well, that's always an option, so it isn't really advice. It's already what
you have to do when the tooling support is bad. It's the poorest when an
editor can instead inline its output of static analysis.

Integration has a lot of benefits like tell you the inference of intermediate
types. "Don't care about good integration" isn't really advice.

It's like people who brag about syntax highlighting. The 99.9% rest of us
consider it a good tool that improves our workflow.

~~~
ahmedalsudani
No dispute integration is nice, but it is not working properly from what my
parent comment was saying.

Your options are to wait for it to improve, fix it yourself, or change your
tools/workflow.

Some people seem to have had an allergic reaction to my comment. Maybe it's
the emacs mention, which was tongue in cheek. Oh well ¯\\_(ツ)_/¯ I'll leave it
as it is... for this is a righteous battle!

~~~
always_good
I don't see a righteous battle.

You mentioned Emacs as a solution which has a Rust plugin that has problems
like most other Rust tooling. Yes, Rust's tooling landscape is immature and
still a work in progress.

Obviously you can just forgo editor integration all together. But you can do
that in any editor.

------
mmastrac
I played around with writing a procedural macro library last night. Being able
to transform functions is amazing (although my example is pretty basic - just
adding some linker metadata to a function).

[https://github.com/mmastrac/rust-ctor](https://github.com/mmastrac/rust-ctor)

------
baby
I'm very interested with Rust on Embedded Devices. I've recently ported my
cryptographic library (www.embeddedDisco.com) to C, thinking it was the only
way to support these many tiny systems, but it looks like it might become less
and less true. I'm still wondering, how are young developers using something
like the Arduino IDE supposed to figure out how to use a Rust library.

~~~
vanderZwan
I wonder if there any compiles-to-C languages will "port" compilers to create
compiles-to-Rust versions. Because there are plenty of those languages out
there in the embedded space.

~~~
gpderetta
What would be the advantage?

~~~
AWildC182
Probably none I'd guess. The embedded space really loves C simply because it's
viewed (usually wrongly) as more deterministic than C++ but there are a lot of
instances where C is not a good choice (when you no-shit need objects) so they
come up with abstractions for common things (terrifying C patterns). Rust has
a lot of features that C lacks so we probably won't need to do any abstraction
for now.

~~~
vanderZwan
Why do you say none, then immediately list a few advantages of Rust? To build
on your points:

\- it might be a easier language to target with a compiler because it's a
higher-level intermediate language

\- there would be fewer undefined behavior shenanigans

\- successfully writing a compiler that targets Rust without using unsafe (too
much) would mean getting (some of) the safety benefits as a side-effect. Could
especially be relevant for languages aiming to introduce zero-overhead safety
to the embedded environment themselves

\- regarding previous point: discovering bugs in the process of porting to
Rust

\- because Rust plays relatively nicely with C and C++, one wouldn't have to
lose existing libraries along the way

~~~
AWildC182
I'm saying "None" in response to needing compilers that compile to Rust, not
to rust itself. Basically to boil down my argument, we don't need to compile
to Rust instead of C because simply replacing C with Rust should be
sufficient. People made "compiles to C" languages because C was not capable of
doing everything they wanted easily.

~~~
vanderZwan
Aaah, I see where you are coming from. Yes, that is a good point.

Porting a compiler could still be useful for the sake of legacy code though.

------
2bitencryption
I'm a huge fan of this "edition" system.

It allows learning from past mistakes, without being bound to supporting those
past mistakes forever...

The module system improvements are so nice. Same with all the other ergonomic
changes. Maybe I would feel differently about Rust if I had to use it
professionally, but as a hobbyist, it's such a joy.

------
Twisol
FYI, if you're on MacOS at least, `rustfmt` looks like it's still under the
`rustfmt-preview` name in `rustup components list`. Running `rustup component
add rustfmt` (as in the official announcement post) gives an error:

    
    
        > rustup component add rustfmt
        error: toolchain 'stable-x86_64-apple-darwin' does not contain component 'rustfmt' for target 'x86_64-apple-darwin'

~~~
steveklabnik
Apparently you need to `rustup self update` before installing this version,
and it will work. So if you've installed it, uninstall it, then update rustup,
then reinstall it. Sorry about that! There was a miscommunication...

~~~
doodpants
I'm seeing the same problem on Windows:

    
    
      $ rustup component add rustfmt
      error: toolchain 'stable-x86_64-pc-windows-msvc' does not contain component 'rustfmt' for target 'x86_64-pc-windows-msvc'
    

I looked for how to uninstall rust, and found that "the book" says that the
command 'rustup self uninstall' will uninstall both rust and rustup. So I
figured, what the heck, I'll start from scratch. I ran this command,
uninstalling everything. Then I re-downloaded rustup-init.exe, and then ran
it, reinstalling rust. I even then did 'rustup self update' and 'rustup
update' for good measure.

I still get the same error when trying to install rustfmt. What else is there
to do if completely uninstalling and reinstalling doesn't work?

~~~
steveklabnik
Theres a bug! We’re working on it. I should have an update for you soon.

~~~
doodpants
Ok, thanks!

~~~
steveklabnik
This should be fixed now, please try again!

~~~
doodpants
It works! (After uninstalling, and then re-downloading and running rustup-
init.exe)

------
SCdF
Incredibly excited for those lifetime improvements. Rust is cool and
everything, but (at least for someone who comes from a memory managed runtime
background) lifetimes are a hard pill to swallow. Anything that makes them go
down easier is gladly received.

------
vvanders
Good stuff.

One small note on WASM, I really hope that wasm32-unknown-emscripten doesn't
become an orphaned target. I've got quite a few WASM/ASM.js projects that have
C dependencies which work great with WASM. Unfortunately wasm-bindgen and the
like appear to require wasm32-unknown-unknown and since the cc crate doesn't
work with wasm32-unknown-unknown I can't take advantage of them.

Totally love the wasm32-unknown-unknown target from a easy bootstrapping
standpoint but it feels like that and the traditional target are starting to
diverge pretty significantly(you can't do a cdynlib crate on wasm32-unknown-
emscripten for instance).

~~~
steveklabnik
We’re not removing it any time soon, but we’re also not focused on developing
it any further. Targets based on LLVM’s native support, like the unknown
target, are the future.

~~~
vvanders
Thanks, appreciate the clarification.

Is there any plans in the works to bring the cc crate over to wasm32-unknown-
unknown? Most of the impressive stuff I've been able to do with WASM has been
pairing existing C libraries with Rust in the right ways and it would be
unfortunate to lose access to that whole ecosystem.

~~~
steveklabnik
Not immediate plans, but you are right that it’s a weakness of the new
targets. There’s still so much work to do!

------
jmull
I was surprised by this:

"Rust has quickly become the best language for integrating with existing web
applications."

Is that really true or some PR hyperbole?

~~~
vram22
>"Rust has quickly become the best language for integrating with existing web
applications."

In what senses? Interested to know, being both a CLI and a web dev guy, and
not having looked much into either Rust or wasm yet (read a little of the Rust
book, only, recently).

~~~
steveklabnik
We’re seeing two ways so far: the first is WebAssembly. Our tooling does not
assume that you’re re-writing everything in wasm, but that you’re using it
alongside JS, so you can use it only where it makes sense, and it’s easy to do
so.

Second, in services. Microservice architecture means you can write parts of
your applications in different languages, and we have really nice JSON
handling, or whatever other format you’re using. People have moved high load
services to rust and seen big gains.

Of course, there’s still lots of work to do, and there’s always compelling
reasons to use other technologies too.

~~~
vram22
Thanks for the detailed and balanced answer.

>we have really nice JSON handling, or whatever other format you’re using.

Good to know. Data formats and conversion between them (often, though not
solely, in the context of CLI apps) is one of my interests and areas of
experience, so will check out those aspects of Rust over time.

>People have moved high load services to rust and seen big gains.

Cool ...

~~~
mlindner
Check out Serde. [https://serde.rs/#data-formats](https://serde.rs/#data-
formats)

Lots of things are using it as well
[https://crates.io/crates/serde/reverse_dependencies](https://crates.io/crates/serde/reverse_dependencies)

~~~
vram22
Serde - good product name :)

------
krick
So, is roadmap for 2019 visible? I'm really interested if any high-performance
computing features are going to be introduced or not.

~~~
staticassertion
Some HPC features (const fn) made it into 2018, and will continue to be
developed.

Out of curiosity, what is missing for you? I'd imagine int generics and const
fn, simd. What else?

~~~
krick
I wonder if better support for multi-dimesional arrays and matrix operations
could be implemented.

~~~
staticassertion
Seems like int generics are the blocker here.

------
huntie
I was kind of disappointed with Rust 2018. While it technically maintains the
guarantee of backwards compatibility I don't feel that it meets it in spirit.

The prime example is that code for working with modules that works fine on
2015 throws an error in 2018. This means that I now have to know two languages
that are basically the same but have important differences. This is a real
issue because I'm sure that some crates will jump to 2018 while others want to
continue compiling on old compilers.

~~~
Twisol
My understanding is that, since the edition is a per-crate property, crates
that don't jump to 2018 aren't any worse off, and will continue to compile on
both old and new compilers. I'd also be interested to know whether `cargo fix`
covers the module changes for you.

(EDIT: I now realize you're talking about crates that will continue
development on Rust 2015 specifically because they want to target older
compilers, which is a different concern from what I was addressing. But now
I'm not sure what the concern _actually_ is. Even if you stay on Rust 2015,
what reason is there to not upgrade your compiler? Both editions remain
supported in 1.31 and will be for...ever, as far as I know.)

~~~
huntie
`cargo fix` probably covers it, but `cargo new` defaults to Rust 2018, which
was kind of annoying when I was getting errors on code from another project
that worked fine there.

There isn't a reason not to upgrade the compiler. My concern is that if I stay
with Rust 2015 nothing changes for me, but if I need to fix a bug in someone's
library there is a good chance they'll be on Rust 2018 (or vice versa). My
concern is with the mental aspect of needing to remember the differences, not
the technical differences.

It's possible that there isn't much to remember. Admittedly, I haven't yet
looked at what the module changes are; but it still bothers me that such basic
code no longer works.

~~~
Twisol
That's a great point! Helping devs get up to speed on the changes is
definitely a significant concern for editions, which is, I'm sure, why they
put so much effort into creating a dedicated edition guide: [https://doc.rust-
lang.org/edition-guide/](https://doc.rust-lang.org/edition-guide/)

~~~
huntie
Sure, the rust team is really good about documentation. I think that I worded
things poorly though. One of the reasons that I started using rust is that the
rust team said that once they hit 1.0 they would not make breaking changes
(unless there was a soundness bug). While Rust 2018 technically keeps this
promise since Rust 2015 will continue to compile and interoperate, I do not
feel that it keeps the spirit of this promise; which is frustrating to me.

~~~
tikue_
Backwards-compatibly changing existing features feels qualitatively the same
to me as adding new features. In either case you can ignore them until you
need to work on a codebase that uses them.

------
devj
To all Rustacenas who are running Rust in production, would you create an
"Effective Rust"?

~~~
sidcool
I would buy the book in a heartbeat.

------
moother
Dumb question, does this mean the official Rust book I had shipped yesterday
is outdated?

~~~
steveklabnik
Not at all! It means it isn’t complete. That was always true; we release a new
thing every six weeks.

------
amelius
Shouldn't .rs files declare the version of the language they were written for?
At least optionally?

~~~
Tuna-Fish
With [2018], rust has gone on the path of tightly integrating the build system
into the language. Before, you had to declare the crates you were using with
"extern crate" in your main package. Now, the only place those are found is in
the Cargo.toml build script. The language version is chosen in the same place.

~~~
steveklabnik
This imposes no additional requirements on rustc, it’s the same as it
previously was. Cargo is no more tightly integrated.

~~~
gpm
This makes using rustc without cargo much harder.

For instance, previously I could `rustc src/main.rs -L deps` and assuming that
the dependencies had all been built and had their rlibs put in deps things
would just work. Now that is no longer possible, I have to manually specify
every external dependency on the command line.

~~~
kibwen
`extern crate` hasn't been made a syntax error, it's just now possible to
elide it. There are plenty of use cases where I imagine people will still use
it, not least of which is play.rust-lang.org, which has no direct access to
Cargo or rustc, and `extern crate` is what one will continue to use to import
third-party libraries there.

------
pjmlp
Congratulations on the milestone! Updating right away. :)

------
adultSwim
I really like the changes to the type checker

------
nicoburns
EDIT: Updated to correct URL (as it changed after I posted).

Official Rust blog post: [https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-
rust-201...](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-
rust-2018.html)

(may be inconsistently available for a bit, as they seem to be in the process
of updating the site to a new look)

~~~
jsheard
The URL changed for some reason: [https://blog.rust-
lang.org/2018/12/06/Rust-1.31-and-rust-201...](https://blog.rust-
lang.org/2018/12/06/Rust-1.31-and-rust-2018.html)

~~~
steveklabnik
It's because I noobed out. The old link was an old draft, this is the correct
link.

------
throwaway487550
Still, we want more things to be boldly and shamelessly borrowed from ML and
Haskell

    
    
      * Universal pattern-matching (everywhere)
      * Obvious syntactic sugar for defining and applying curried 
        functions, partial application.
      * Type-classes (as a one single major innovation in PL 
        since Smalltalk)
      * receive (or select) with pattern matching (Erlang, protobuf).
      * first class typed channels (Go).
      * multimethods (CLOS).
    

Thank you!

~~~
paavohtl
> Universal pattern-matching

Where are you missing pattern matching? The only place I can think of where it
can't be used currently is the function signature. Might be hard to retrofit
to the current syntax.

> Type-classes

Rust's traits are type-classes.

> first class typed channels

Why do they need to be first class? Unlike Go, Rust's type system is powerful
enough that type-safe channels can be (and have been) implemented as a
library. See crossbeam-channel.

~~~
steveklabnik
You can use pattern matches in function signatures.

~~~
throwaway487550
How could I write this in Rust?

    
    
        fun map f [] = []
          | map f (x::xs) = (f x) :: map f xs;
    

And boy, no TCO. What a shame.

~~~
steveklabnik
You can only use irrefutable patterns. You’d write this by writing a match in
the body. There’s been talk of maybe supporting this directy but it’s so niche
there’s not a ton of demand.

There _is_ TCO, just not guaranteed. We’d like it; we have even reserved a
keyword. Needs an RFC though.

------
Animats
Why should they need "edition"? Just bump the first number of N.N.N semantic
versioning.

~~~
lalaithion
Because they haven't actually broken backwards compatibility, but rather
allowed people to opt-in to incompatible changes by setting a flag.

~~~
deathanatos
> _haven 't actually broken backwards compatibility_

My understanding from reading the article is that they have broken backwards
compatibility; things using the new keywords that were introduced (e.g.,
"await") will no longer compile.

I think part of the confusion here is that there are essentially two things:
there's the compiler, and there is the language itself. It appears (from the
article) the compiler can presently support compiling either "edition 2015" or
"edition 2018" of the language. (So, it's not the compiler's major we're
bumping, rather, it's the language's.)

That flag which says which "edition" to use could just as easily specify which
SemVer major version to use. So, instead of saying "use Rust edition 2015" or
"edition 2018" it would just be "Rust (the language) v1" or "Rust (the
language) v2". There's no difference aside from the naming.

The year doesn't particularly add anything, and obscures if we're jumping over
multiple "barriers" of breaking changes or not. I'm not actually sure that
that really matters.

My only thought is that having completely different looking things might be
better in that it just visually distinguishes the two better. I've repeatedly
seen devs muddle the difference between the language, and a implementation of
the language, and what the language guarantees and what the implementation
happens to do.

~~~
oconnor663
> things using the new keywords that were introduced (e.g., "await") will no
> longer compile

That's not backwards compatibility, it's forwards compatibility. Whenever any
language adds a new feature, using that feature breaks the build on old
compilers. Setting `edition=2018` is no different. But the important thing is
that old code continues to build unmodified on new compilers. That's what the
edition system is preserving.

~~~
deathanatos
Forwards compatibility would be old code compiling in the newer "language",
and I mean this from the grammar perspective: that the changes to the grammar
are such that all things that were previously valid in the language remain as
valid, and their meaning does not change.

This is not the case.

That the compiler has the user opt-in to the never version by setting a flag
is irrelevant, for the discussion of versioning. (Now, for an end-user, I
think it's great: you do _not_ want to automatically break working code. I'm
not saying the flag shouldn't exist, I'm saying the flag exists _because_ the
change is breaking.)

~~~
oconnor663
You're right, I totally misread the above.

------
v_lisivka
Incompatibility with C enums in repr(C) enums is still not fixed.

In C, enums are more like:

    
    
      #[repr(C)]
      enum Foo {
        BAR=0,
        BAZ=1,
        Unknown(i32), // other possible values of int
      };
    

but Rust doesn't allow to write enums like that, so it leads to bugs in FFI.

~~~
kibwen
It's true that C allows manually setting an enum to an integral value other
than those explicitly specified, but no project that I've ever seen regards
such an action as anything other than a bug. Can you give an example of code
that's using such a thing, especially for FFI?

~~~
olliej
The Mac and iOS design uses explicitly valued enums in all APIs (aside from
anything else it makes it much harder to accidentally break ABI).

JSC also uses them extensively in the lexer and parser.

~~~
kibwen
Rust can do explicit values for C-style enums; what it currently doesn't
support is the ability to set such an enum to an arbitrary (non-declared)
value as C does.

------
gntech
The headline calls for these legendary clips from Red Dwarf to be inserted
into the comments.

[https://www.youtube.com/watch?v=TxWN8AhNER0](https://www.youtube.com/watch?v=TxWN8AhNER0)

[https://www.youtube.com/watch?v=3r5Ynz-a7Io](https://www.youtube.com/watch?v=3r5Ynz-a7Io)

------
strgrd
Crazy to think how far Rust has come since 2013. Very excited for the
electricity update coming later today -- I've already seen a few videos of
people implementing basic computer systems. I imagine there won't be many
people falling for bases with open doors this wipe... Still frustrating to see
basic optimizations in the pipeline. Many users have been suffering from
microstutters for years. Regardless, there is nothing else out there like
Rust, and for that I wish the Facepunch team a happy 5th birthday!

~~~
nicoburns
I believe you are talking about Rust the game, whereas this post is about Rust
the programming language.

~~~
sieabahlpark
What a headline reader.

~~~
reificator
[https://www.youtube.com/watch?v=dU95v23MQ4c](https://www.youtube.com/watch?v=dU95v23MQ4c)

