|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Announcing Rust 1.17" |
| 4 | +author: The Rust Core Team |
| 5 | +--- |
| 6 | + |
| 7 | +The Rust team is happy to announce the latest version of Rust, 1.17.0. Rust is a |
| 8 | +systems programming language focused on safety, speed, and concurrency. |
| 9 | + |
| 10 | +If you have a previous version of Rust installed, getting Rust 1.17 is as easy as: |
| 11 | + |
| 12 | +```bash |
| 13 | +$ rustup update stable |
| 14 | +``` |
| 15 | + |
| 16 | +If you don't have it already, you can [get `rustup`][install] from the |
| 17 | +appropriate page on our website, and check out the [detailed release notes for |
| 18 | +1.17.0][notes] on GitHub. |
| 19 | + |
| 20 | +[install]: https://www.rust-lang.org/install.html |
| 21 | +[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1170-2017-04-27 |
| 22 | + |
| 23 | +### What's in 1.17.0 stable |
| 24 | + |
| 25 | +The story of Rust 1.17.0 is mostly one of small, quality of life improvements. For example, |
| 26 | +[the `'static` lifetime is now assumed in statics and consts](https://github.com/rust-lang/rust/pull/39265). When writing a const or static like this: |
| 27 | + |
| 28 | +```rust |
| 29 | +const NAME: &'static str = "Ferris"; |
| 30 | +static NAME: &'static str = "Ferris"; |
| 31 | +``` |
| 32 | + |
| 33 | +Rust 1.17 will allow you to elide the `'static`, since that's the only lifetime that makes |
| 34 | +sense: |
| 35 | + |
| 36 | +```rust |
| 37 | +const NAME: &str = "Ferris"; |
| 38 | +static NAME: &str = "Ferris"; |
| 39 | +``` |
| 40 | + |
| 41 | +In some situations, this can remove lots of boilerplate: |
| 42 | + |
| 43 | +```rust |
| 44 | +// old |
| 45 | +const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"]; |
| 46 | + |
| 47 | +// new |
| 48 | +const NAMES: &[&str; 2] = &["Ferris", "Bors"]; |
| 49 | +``` |
| 50 | + |
| 51 | +Another similar improvement is "field init shorthand." Similar to ECMAScript 6, |
| 52 | +which calls this "Object Literal Property Value Shorthand", duplication can be |
| 53 | +removed when declaring structs, like this: |
| 54 | + |
| 55 | +```rust |
| 56 | +// definitions |
| 57 | +struct Point { |
| 58 | + x: i32, |
| 59 | + y: i32, |
| 60 | +} |
| 61 | + |
| 62 | +let x = 5; |
| 63 | +let y = 6; |
| 64 | + |
| 65 | +// old |
| 66 | +let p = Point { |
| 67 | + x: x, |
| 68 | + y: y, |
| 69 | +}; |
| 70 | + |
| 71 | +// new |
| 72 | +let p = Point { |
| 73 | + x, |
| 74 | + y, |
| 75 | +}; |
| 76 | +``` |
| 77 | + |
| 78 | +That is, the `x, y` form will assume that its values are set to a varaible |
| 79 | +with the same name in its scope. |
| 80 | + |
| 81 | +In a similar way, it's common for new Rustaceans to try to use `+` to add two |
| 82 | +`&str`s together. This doesn't work, you can only add `String + &str`. As |
| 83 | +such, [a new error message](https://github.com/rust-lang/rust/pull/39116) |
| 84 | +was added to help users who make this mistake: |
| 85 | + |
| 86 | +```rust |
| 87 | +// code |
| 88 | +"foo" + "bar" |
| 89 | + |
| 90 | +// old |
| 91 | +error[E0369]: binary operation `+` cannot be applied to type `&'static str` |
| 92 | + --> <anon>:2:5 |
| 93 | + | |
| 94 | +2 | "foo" + "bar" |
| 95 | + | ^^^^^ |
| 96 | + | |
| 97 | +note: an implementation of `std::ops::Add` might be missing for `&'static str` |
| 98 | + --> <anon>:2:5 |
| 99 | + | |
| 100 | +2 | "foo" + "bar" |
| 101 | + | ^^^^^ |
| 102 | + |
| 103 | +// new |
| 104 | +error[E0369]: binary operation `+` cannot be applied to type `&'static str` |
| 105 | + --> <anon>:2:5 |
| 106 | + | |
| 107 | +2 | "foo" + "bar" |
| 108 | + | ^^^^^ |
| 109 | + | |
| 110 | + = note: `+` can't be used to concatenate two `&str` strings |
| 111 | +help: to_owned() can be used to create an owned `String` from a string |
| 112 | +reference. String concatenation appends the string on the right to the string on |
| 113 | +the left and may require reallocation. This requires ownership of the string on |
| 114 | +the left. |
| 115 | + | "foo".to_owned() + "bar" |
| 116 | +``` |
| 117 | + |
| 118 | +When using Cargo's build scripts, you must set the location of the script in your |
| 119 | +`Cargo.toml`. However, the vast majority of people wrote `build = "build.rs"`, using |
| 120 | +a `build.rs` file in the root of their project. [This convention is now encoded |
| 121 | +into Cargo](https://github.com/rust-lang/cargo/pull/3664), and will be assumed if |
| 122 | +`build.rs` exists. We've been warning about this change for the past few releases, |
| 123 | +and you can use `build = false` to opt out. |
| 124 | + |
| 125 | +This release marks [the removal](https://github.com/rust-lang/rust/pull/39431) |
| 126 | +of the old `Makefile` based build system. We announced this new system in 1.15, |
| 127 | +which is written in Rust and primarily uses Cargo to drive the build, and now |
| 128 | +it is mature enough to always use. |
| 129 | + |
| 130 | +As part of that change, packages from crates.io can now be used within Rust's |
| 131 | +build system. The first one to be added was [mdBook](https://crates.io/crates/mdbook), |
| 132 | +and [it's now being used](https://github.com/rust-lang/rust/pull/39633) to render |
| 133 | +our various book-like documentation: |
| 134 | + |
| 135 | +* [The book](https://doc.rust-lang.org/stable/book/) ([repo](https://github.com/rust-lang/book)) |
| 136 | +* [The reference](https://doc.rust-lang.org/stable/reference/) ([repo](https://github.com/rust-lang-nursery/reference)) |
| 137 | +* [The nomicon](https://doc.rust-lang.org/stable/nomicon/) ([repo](https://github.com/rust-lang-nursery/nomicon)) |
| 138 | + |
| 139 | +In addition, see those links to their respective repositories; they've been |
| 140 | +moved out of tree. Also, we've added a fourth book, still in-tree: [The |
| 141 | +Unstable Book](https://doc.rust-lang.org/stable/unstable-book/). This |
| 142 | +provides an overview of unstable features by name, contains links to their |
| 143 | +tracking issues, and may contain initial documentation of the feature. |
| 144 | +If there's a feature you want to see stabilized, please get involved on |
| 145 | +its tracking issue! |
| 146 | + |
| 147 | +A few releases ago, `rustup` stopped installing documentation |
| 148 | +by default. We made this change to save some bandwidth and because not |
| 149 | +all users want a copy of the documentation locally. However, this created |
| 150 | +a pitfall: some users did not realize that this changed, and would only |
| 151 | +notice once they were no longer connected to the internet. In addition, |
| 152 | +some users *did* want to have a local copy of the docs, regardless of |
| 153 | +their connectivity. As such, we've [reverted the change](https://github.com/rust-lang/rust/pull/40526), and documentation is being |
| 154 | +installed by default again. |
| 155 | + |
| 156 | +Finally, while this release is full of improvements, there is one small |
| 157 | +step back we want to regretfully inform you about. On Windows, Visual |
| 158 | +Studio 2017 has been released, and Microsoft has changed the structure |
| 159 | +of how the software is installed. [Rust cannot automatically detect this |
| 160 | +location](https://github.com/rust-lang/rust/issues/38584), and while we |
| 161 | +were working on the neccesary changes, they did not make it in time for |
| 162 | +this release. Until then, Visual Studio 2015 still works fine, or you |
| 163 | +can run `vcvars.bat` on the command line. We hope to make this work |
| 164 | +in a seamless fashion soon. |
| 165 | + |
| 166 | +See the [detailed release notes][notes] for more. |
| 167 | + |
| 168 | +#### Library stabilizations |
| 169 | + |
| 170 | +17 new bits of API were stabilized this release: |
| 171 | + |
| 172 | +* [`Arc::into_raw`] and [`Rc::into_raw`] let you consume an `Arc` or `Rc` and get a raw pointer. |
| 173 | +* [`Arc::from_raw`] and [`Rc::from_raw`] let you take that raw pointer and get an `Arc` or `Rc`. |
| 174 | +* [`Ordering::then`] lets you chain two `Ordering`s together, and [`Ordering::then_with`] lets you do it with a function. |
| 175 | +* [`BTreeMap::range`] allows you to iterate over a portion of a `BTreeMap`, and [`BTreeMap::range_mut`] lets you do it mutably. [`collections::Bound`] can give you even more control. |
| 176 | +* [`process::abort`] will completely terminate a process in an abnormal fashion. |
| 177 | +* [`ptr::read_unaligned`] and [`ptr::write_unaligned`] are like `ptr::read` and `ptr::write`, but without alignment requirements. |
| 178 | +* [`Result::expect_err`] mirrors `Result::expect`, but with the `Err` case rather than the `Ok` case. |
| 179 | +* [`Cell::swap`] is similar to `std::mem::swap`, but lets you do it with `&Cell` instead of `&mut T`. |
| 180 | +* [`Cell::replace`] is similar to `std::mem::replace`, but lets you do it with `&Cell` instead of `&mut T`. |
| 181 | +* [`Cell::into_inner`] lets you consume the `Cell`, and extract its value. |
| 182 | +* [`Cell::take`] lets you take the value out of a `Cell`, leaving its `Default::default` behind. |
| 183 | + |
| 184 | +[`Arc::from_raw`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.from_raw |
| 185 | +[`Arc::into_raw`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.into_raw |
| 186 | +[`BTreeMap::range_mut`]: https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.range_mut |
| 187 | +[`BTreeMap::range`]: https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.range |
| 188 | +[`Cell::into_inner`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.into_inner |
| 189 | +[`Cell::replace`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.replace |
| 190 | +[`Cell::swap`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.swap |
| 191 | +[`Cell::take`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.take |
| 192 | +[`Ordering::then_with`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then_with |
| 193 | +[`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then |
| 194 | +[`Rc::from_raw`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.from_raw |
| 195 | +[`Rc::into_raw`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.into_raw |
| 196 | +[`Result::expect_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect_err |
| 197 | +[`collections::Bound`]: https://doc.rust-lang.org/std/collections/enum.Bound.html |
| 198 | +[`process::abort`]: https://doc.rust-lang.org/std/process/fn.abort.html |
| 199 | +[`ptr::read_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html |
| 200 | +[`ptr::write_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html |
| 201 | + |
| 202 | +In other changes, `Cell<T>` used to require that `T: Copy` for many of its methods, |
| 203 | +but [this has been relaxed significantly](https://github.com/rust-lang/rust/pull/39793). |
| 204 | + |
| 205 | +`Box<T>` [now implements](https://github.com/rust-lang/rust/pull/40009) over a dozen new |
| 206 | +conversions with `From`. |
| 207 | + |
| 208 | +`SocketAddr` and `IpAddr` have [some new conversions](https://github.com/rust-lang/rust/pull/39372) |
| 209 | +as well. Previously, you may have written code like this: |
| 210 | + |
| 211 | +```rust |
| 212 | +"127.0.0.1:3000".parse().unwrap() |
| 213 | +``` |
| 214 | + |
| 215 | +Now, you can write |
| 216 | + |
| 217 | +```rust |
| 218 | +SocketAddr::from(([127, 0, 0, 1], 3000)) |
| 219 | +// or even |
| 220 | +([127, 0, 0, 1], 3000).into()) |
| 221 | +`` |
| 222 | + |
| 223 | +This removes some uneccesary run-time parsing, and is roughly as readable, depending on |
| 224 | +your preferences. |
| 225 | + |
| 226 | +Backtraces [now have nicer formatting](https://github.com/rust-lang/rust/pull/38165), eliding |
| 227 | +many internal stack frames by default. For example, the full backtrace: |
| 228 | + |
| 229 | +```text |
| 230 | +thread 'main' panicked at 'This function never returns!', t.rs:2 |
| 231 | +stack backtrace: |
| 232 | + 0: 0x558ddf666478 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hec84c9dd8389cc5d |
| 233 | + at /home/yamakaky/dev/rust/rust/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 |
| 234 | + 1: 0x558ddf65d90e - std::sys_common::backtrace::_print::hfa25f8b31f4b4353 |
| 235 | + at /home/yamakaky/dev/rust/rust/src/libstd/sys_common/backtrace.rs:71 |
| 236 | + 2: 0x558ddf65cb5e - std::sys_common::backtrace::print::h9b711e11ac3ba805 |
| 237 | + at /home/yamakaky/dev/rust/rust/src/libstd/sys_common/backtrace.rs:60 |
| 238 | + 3: 0x558ddf66796e - std::panicking::default_hook::{{closure}}::h736d216e74748044 |
| 239 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:355 |
| 240 | + 4: 0x558ddf66743c - std::panicking::default_hook::h16baff397e46ea10 |
| 241 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:371 |
| 242 | + 5: 0x558ddf6682bc - std::panicking::rust_panic_with_hook::h6d5a9bb4eca42c80 |
| 243 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:559 |
| 244 | + 6: 0x558ddf64ea93 - std::panicking::begin_panic::h17dc549df2f10b99 |
| 245 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:521 |
| 246 | + 7: 0x558ddf64ec42 - t::diverges::he6bc43fc925905f5 |
| 247 | + at /tmp/p/t.rs:2 |
| 248 | + 8: 0x558ddf64ec5a - t::main::h0ffc20356b8a69c0 |
| 249 | + at /tmp/p/t.rs:6 |
| 250 | + 9: 0x558ddf6687f5 - core::ops::FnOnce::call_once::hce41f19c0db56f93 |
| 251 | + 10: 0x558ddf667cde - std::panicking::try::do_call::hd4c8c97efb4291df |
| 252 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:464 |
| 253 | + 11: 0x558ddf698d77 - __rust_try |
| 254 | + 12: 0x558ddf698c57 - __rust_maybe_catch_panic |
| 255 | + at /home/yamakaky/dev/rust/rust/src/libpanic_unwind/lib.rs:98 |
| 256 | + 13: 0x558ddf667adb - std::panicking::try::h2c56ed2a59ec1d12 |
| 257 | + at /home/yamakaky/dev/rust/rust/src/libstd/panicking.rs:440 |
| 258 | + 14: 0x558ddf66cc9a - std::panic::catch_unwind::h390834e0251cc9af |
| 259 | + at /home/yamakaky/dev/rust/rust/src/libstd/panic.rs:361 |
| 260 | + 15: 0x558ddf6809ee - std::rt::lang_start::hb73087428e233982 |
| 261 | + at /home/yamakaky/dev/rust/rust/src/libstd/rt.rs:57 |
| 262 | + 16: 0x558ddf64ec92 - main |
| 263 | + 17: 0x7fecb869e290 - __libc_start_main |
| 264 | + 18: 0x558ddf64e8b9 - _start |
| 265 | + 19: 0x0 - <unknown> |
| 266 | +``` |
| 267 | +
|
| 268 | +is now instead |
| 269 | +
|
| 270 | +```text |
| 271 | +thread 'main' panicked at 'explicit panic', t.rs:2 |
| 272 | +Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. |
| 273 | +stack backtrace: |
| 274 | + 0: t::fail |
| 275 | + at ./t.rs:2 |
| 276 | + 1: t::main::{{closure}} |
| 277 | + at ./t.rs:6 |
| 278 | + 2: t::main |
| 279 | + at ./t.rs:7 |
| 280 | +``` |
| 281 | +
|
| 282 | +By default. As the message says, you can set an environment variable to get the full |
| 283 | +backtrace. |
| 284 | +
|
| 285 | +See the [detailed release notes][notes] for more. |
| 286 | +
|
| 287 | +#### Cargo features |
| 288 | +
|
| 289 | +Other than the previous mentioned `build.rs` changes, Cargo has a few new improvements. |
| 290 | +[`cargo check --all`](https://github.com/rust-lang/cargo/pull/3731) and |
| 291 | +[`cargo run --package`](https://github.com/rust-lang/cargo/pull/3691) are two missing |
| 292 | +flags that are now supported. |
| 293 | +
|
| 294 | +You can now [opt in to ignoring SSL revocation checks](https://github.com/rust-lang/cargo/pull/3699). The default is still to check, of course. |
| 295 | +
|
| 296 | +A new field in `Cargo.toml`, `required-features`, lets you [specify specific features |
| 297 | +that must be set for a target to be built](https://github.com/rust-lang/cargo/pull/3667). |
| 298 | +Here's an example: let's say that we are writing a crate that interacts with databases, |
| 299 | +and that we support multiple databases. We might have this in our `Cargo.toml`: |
| 300 | + |
| 301 | +```toml |
| 302 | +[features] |
| 303 | +# ... |
| 304 | +postgres = [] |
| 305 | +sqlite = [] |
| 306 | +tools = [] |
| 307 | +``` |
| 308 | + |
| 309 | +The `tools` feature allows us to include extra tooling, and the `postgres` and `sqlite` |
| 310 | +features control which databses we want to support. |
| 311 | + |
| 312 | +Previously, `cargo build` would attempt to build all targets, which is normally what |
| 313 | +you want. But what if we had a `src/bin/postgres-tool.rs`, that would only really |
| 314 | +be relevant if the `postgres` and `tools` features would be enabled? Previously, |
| 315 | +we would have to write something like this: |
| 316 | + |
| 317 | +```rust |
| 318 | +#[cfg(not(all(feature = "postgres", feature = "tools")))] |
| 319 | +fn main() { |
| 320 | + println!("This tool requires the `postgres` and `tools` features to be enabled."); |
| 321 | +} |
| 322 | + |
| 323 | +#[cfg(all(feature = "postgres", feature = "tools"))] |
| 324 | +fn main() { |
| 325 | + // real code |
| 326 | +} |
| 327 | +``` |
| 328 | + |
| 329 | +This is a lot of boilerplate to work around `cargo build`'s behavior. It's even |
| 330 | +more unfortunate with `examples/`, which are supposed to show off how to use |
| 331 | +your library, but this shenanigans is only relevant within the package, not if |
| 332 | +you were to try to use the example on your own. |
| 333 | + |
| 334 | +With the new `required-features` key, we can add this: |
| 335 | + |
| 336 | +```toml |
| 337 | +[[bin]] |
| 338 | +# ... |
| 339 | +required-features = ["postgres", "tools"] |
| 340 | +``` |
| 341 | + |
| 342 | +Now, `cargo build` will only build our `postgres-tool` if we have the two features |
| 343 | +set, and so we can write a normal `fn main` without all the `cfg` nonsense getting |
| 344 | +in the way. |
| 345 | + |
| 346 | +See the [detailed release notes][notes] for more. |
| 347 | + |
| 348 | +### Contributors to 1.17.0 |
| 349 | + |
| 350 | +Many people came together to create Rust 1.17. We couldn't have done it without |
| 351 | +all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.17.0) |
0 commit comments