-
Notifications
You must be signed in to change notification settings - Fork 288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust 1.30 #281
Rust 1.30 #281
Changes from 1 commit
cfe470c
c57ade2
2906893
7fdf631
f2b7528
2680b32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,355 @@ | ||
--- | ||
layout: post | ||
title: "Announcing Rust 1.30" | ||
author: The Rust Core Team | ||
--- | ||
|
||
The Rust team is happy to announce a new version of Rust, 1.30.0. Rust is a | ||
systems programming language focused on safety, speed, and concurrency. | ||
|
||
If you have a previous version of Rust installed via rustup, getting Rust | ||
1.30.0 is as easy as: | ||
|
||
```bash | ||
$ rustup update stable | ||
``` | ||
|
||
If you don't have it already, you can [get `rustup`][install] from the | ||
appropriate page on our website, and check out the [detailed release notes for | ||
1.30.0][notes] on GitHub. | ||
|
||
[install]: https://www.rust-lang.org/install.html | ||
[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1300-2018-10-25 | ||
|
||
## What's in 1.30.0 stable | ||
|
||
Rust 1.30 is an exciting release with a number of features. On Monday, expect another | ||
blog post asking you to check out Rust 1.31's beta; Rust 1.31 will be the first release | ||
of "Rust 2018." For more on that concept, please see our previous post | ||
["What is Rust 2018"](https://blog.rust-lang.org/2018/07/27/what-is-rust-2018.html). | ||
|
||
## Procedural Macros | ||
|
||
Way back in [Rust 1.15], we announced the ability to define "custom derives." For example, | ||
with `serde_json`, you could | ||
|
||
```rust | ||
#[derive(Serialize, Deserialize, Debug)] | ||
struct Pet { | ||
name: String, | ||
} | ||
``` | ||
|
||
And convert a `Pet` to and from JSON. | ||
|
||
Rust expands on this by adding the ability to define two other kinds of | ||
advanced macros, "attribute-like procedrual macros" and "function-like | ||
procedural macros." | ||
|
||
Attribute-like macros are similar to custom derive macros, but instead of | ||
generating code for `#[derive]`, they allow you to create new, custom | ||
attributes of your own. They're also more flexible; derive only works for | ||
structs and enums; attributes can go on other places as well, like functions. | ||
As an example of using an attribute-like macro, you might have something like | ||
this when using a web application framework: | ||
|
||
``` | ||
#[route(GET, "/")] | ||
fn index() { | ||
``` | ||
|
||
This `#[route]` attribute would be defined by the framework itself, as a | ||
procedural macro. Its signature would look like this: | ||
|
||
``` | ||
#[proc_macro_attribute] | ||
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream { | ||
``` | ||
|
||
Here, we have two input `TokenStreams`; the first is for the contents of the | ||
attribute itself, that is, the `GET, "/"` stuff. The second is the body of the | ||
thing the attribute is attached to, in this case, `fn index() {}` and the rest | ||
of the function's body. | ||
|
||
Function-like macros define macros that look like function calls. For | ||
example, an `sql!` macro: | ||
|
||
```rust | ||
let sql = sql!(SELECT * FROM posts WHERE id=1); | ||
``` | ||
|
||
This macro would parse the SQL statement inside of it and check that it's | ||
syntactically correct. This macro would be defined like this: | ||
|
||
``` | ||
#[proc_macro] | ||
pub fn sql(input: TokenStream) -> TokenStream { | ||
``` | ||
|
||
This is similar to the derive macro's signature: we get in the tokens that | ||
are inside of the parentheses, and return the code we wanted to generate. | ||
|
||
### `use` and macros | ||
|
||
You can now [use `use` to bring macros into scope][externmacro]. For example, | ||
to use `serde-json`'s `json` macro, you used to write: | ||
|
||
```rust | ||
#[macro_use] | ||
extern crate serde_json; | ||
|
||
let john = json!({ | ||
"name": "John Doe", | ||
"age": 43, | ||
"phones": [ | ||
"+44 1234567", | ||
"+44 2345678" | ||
] | ||
}); | ||
``` | ||
|
||
But now, you'd write | ||
|
||
```rust | ||
extern crate serde_json; | ||
|
||
use serde_json::json; | ||
|
||
let john = json!({ | ||
"name": "John Doe", | ||
"age": 43, | ||
"phones": [ | ||
"+44 1234567", | ||
"+44 2345678" | ||
] | ||
}); | ||
``` | ||
|
||
This brings macros more in line with other items, and removes the need for | ||
`macro_use` annotations. | ||
|
||
[externmacro]: https://github.com/rust-lang/rust/pull/50911/ | ||
[Rust 1.15]: https://blog.rust-lang.org/2017/02/02/Rust-1.15.html | ||
|
||
## Module system improvements | ||
|
||
The module system has long been a pain point of new Rustaceans; several of | ||
its rules felt awkward in practice. These changes are the first steps we're | ||
taking to make the module system feel more straightforward. | ||
|
||
[`mod.rs` files are now optional][optionalmod]. Imagine we had a `foo` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is un-stabilized again in rust-lang/rust#55315 due to issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can mention tool attributes instead (like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, I've just opened up rust-lang/rust#55331. The Edit: I've confirmed that 1.30 doesn't actually generate a warning on this when running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jtgeibel There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @petrochenkov thanks a lot for the clarification, I wasn't aware those were separate. If it is added to the blog post it may be worth clarifying the distinction because I could see others being confused as well. |
||
submodule, with a `bar` submodule of its own. The directory layout would | ||
look like this: | ||
|
||
```text | ||
. | ||
├── src | ||
│ ├── foo | ||
│ │ └── mod.rs | ||
│ │ └── bar.rs | ||
│ └── lib.rs | ||
``` | ||
|
||
In Rust 1.30, you can do this instead: | ||
|
||
```text | ||
. | ||
├── src | ||
│ ├── foo | ||
│ │ └── bar.rs | ||
│ ├── foo.rs | ||
│ └── lib.rs | ||
``` | ||
|
||
This means that you'll no longer have plenty of tabs all named `mod.rs` in | ||
your IDE! It also eases the process of adding a submodule; before `bar` | ||
existed, the project would look like this: | ||
|
||
```text | ||
. | ||
├── src | ||
│ ├── foo.rs | ||
│ └── lib.rs | ||
``` | ||
|
||
Many users found the need to move `foo.rs` into `foo/mod.rs` to be an | ||
unncessary, strage requirement. With the new layout, you create `src/foo` and | ||
put `bar.rs` in it and you're done. | ||
|
||
[optionalmod]: https://github.com/rust-lang/rust/pull/54072 | ||
|
||
There's two changes to `use` as well. Well, three changes: we already | ||
mentioned that you can use `use` to bring macros into scope in the macros | ||
section. There's two more. The first is that you can [`use` an extern crate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This not about |
||
without needing `::`][nocoloncolon], that is: | ||
|
||
```rust | ||
// old | ||
let json = ::serde_json::from_str("..."); | ||
|
||
// new | ||
let json = serde_json::from_str("..."); | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't demonstrate |
||
|
||
The trick here is that the 'old' style wasn't always needed, due to the way Rust's | ||
module system worked: | ||
|
||
```rust,ignore | ||
extern crate serde_json; | ||
|
||
fn main() { | ||
// this works just fine; we're in the crate root, so `serde_json` is in | ||
// scope here | ||
let json = serde_json::from_str("..."); | ||
} | ||
|
||
mod foo { | ||
fn bar() { | ||
// this doesn't work; we're inside the `foo` namespace, and `serde_json` | ||
// isn't declared there | ||
let json = serde_json::from_str("..."); | ||
|
||
} | ||
|
||
// one option is to `use` it inside the module | ||
use serde_json; | ||
|
||
fn baz() { | ||
// the other option is to use `::serde_json`, so we're using an absolute path rather than | ||
// a relative one | ||
let json = ::serde_json::from_str("..."); | ||
} | ||
} | ||
``` | ||
|
||
Moving a function to a submodule and having your imports break was not a | ||
great experience. Now, `use` will check to see if the first part of the path | ||
and see if it's one of your `extern crate`s, and if it is, use it, regardless | ||
of where you're at in the module hierarchy. | ||
|
||
[nocoloncolon]: https://github.com/rust-lang/rust/pull/54404/ | ||
|
||
Finally, you can also [use `crate` with `use`][usecrate]: | ||
|
||
```rust | ||
mod foo { | ||
pub fn bar() { | ||
// ... | ||
} | ||
} | ||
|
||
// old | ||
use ::foo::bar; | ||
|
||
// new | ||
use crate::foo::bar; | ||
``` | ||
|
||
The `crate` keyword at the start of the path indicates that you would like | ||
the path to start at your crate root. `use` previously would always start at | ||
the crate root, but other paths would start at the local path, meaning: | ||
|
||
```rust | ||
mod foo { | ||
pub fn bar() { | ||
// ... | ||
} | ||
} | ||
|
||
mod baz { | ||
pub fn qux() { | ||
// old | ||
::foo::bar(); | ||
|
||
// new | ||
crate::foo::bar(); | ||
} | ||
} | ||
``` | ||
|
||
This will hopefully make absolute paths a bit more clear, and remove some of | ||
the ugliness of leading `::`. | ||
|
||
All of these changes combined lead to a more straightforward understanding of | ||
how paths resolve. When you see a path like `a::b::c`, you can ask: | ||
|
||
* Is `a` the name of a crate? Then we're looking for `b::c` inside of it. | ||
* Is `a` the keyword `crate`? Then we're looking for `b::c` from the root of our crate. | ||
* Otherwise, we're looking for `a::b::c` from the current spot in the module hierarchy. | ||
|
||
Since these rules apply uniformly everywhere, you'll need to tweak your | ||
imports much less when moving code around. | ||
|
||
[usecrate]: https://github.com/rust-lang/rust/pull/54404/ | ||
|
||
## Raw Identifiers | ||
|
||
[You can now use keywords as identifiers][rawidents] with some new syntax: | ||
|
||
```rust | ||
// define a local variable named `for` | ||
let r#for = true; | ||
|
||
// define a function named `for` | ||
fn r#for() { | ||
// ... | ||
} | ||
|
||
// call that function | ||
r#for(); | ||
``` | ||
|
||
This doesn't have many use cases today, but will once you are trying to use a | ||
Rust 2015 crate with a Rust 2018 project, and vice-versa; we'll explain more | ||
in that upcoming blog post. | ||
|
||
[rawidents]: https://github.com/rust-lang/rust/pull/53236/ | ||
|
||
## Other things | ||
|
||
Finally, you can [use the `#[panic_handler]`][panichandler] attribute to | ||
implement panics yourself, and you can now [match on visibility keywords, | ||
like `pub`, in macros][viskeyword] using the `vis` specifier. | ||
|
||
[panichandler]: https://github.com/rust-lang/rust/pull/51366/ | ||
[viskeyword]: https://github.com/rust-lang/rust/pull/53370/ | ||
|
||
See the [detailed release notes][notes] for more. | ||
|
||
### Library stabilizations | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it makes sense to mention proc macro API here (https://doc.rust-lang.org/stable/proc_macro/index.html). |
||
|
||
A few new APIs were [stabilized for this | ||
release](https://github.com/rust-lang/rust/blob/master/RELEASES.md#stabilized-apis): | ||
|
||
* `Ipv4Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}` | ||
* `Ipv6Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}` | ||
* `Iterator::find_map` | ||
|
||
Additionally, the standard library has long had functions like `trim_left` to eliminate | ||
whitespace on one side of some text. However, when considering RTL languages, the meaning | ||
of "right" and "left" get confusing. As such, we're introducing some new names for these | ||
APIs: | ||
|
||
* `trim_left` -> `trim_start` | ||
* `trim_right` -> `trim_end` | ||
* `trim_left_matches` -> `trim_start_matches` | ||
* `trim_right_matches` -> `trim_end_matches` | ||
|
||
We plan to deprecate (but not removing, of course) the old names in Rust | ||
1.33. | ||
|
||
See the [detailed release notes][notes] for more. | ||
|
||
### Cargo features | ||
|
||
The largest feature of Cargo in this release is that we now [have a progress | ||
bar!](https://github.com/rust-lang/cargo/pull/5995/) | ||
|
||
> GIF goes here | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a reminder to put the gif here (or maybe asciinema?). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a GIF is nicer as it starts automatically, so it is more eye-catching. |
||
|
||
See the [detailed release notes][notes] for more. | ||
|
||
## Contributors to 1.30.0 | ||
|
||
Many people came together to create Rust 1.30. We couldn't have done it | ||
without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.30.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is being dropped from the release (last minute bug found)