|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Announcing Rust 1.35.0" |
| 4 | +author: The Rust Release Team |
| 5 | +release: true |
| 6 | +--- |
| 7 | + |
| 8 | +The Rust team is happy to announce a new version of Rust, 1.35.0. Rust is a |
| 9 | +programming language that is empowering everyone to build reliable and efficient software. |
| 10 | + |
| 11 | +If you have a previous version of Rust installed via rustup, getting Rust 1.35.0 is as easy as: |
| 12 | + |
| 13 | +```console |
| 14 | +$ rustup update stable |
| 15 | +``` |
| 16 | + |
| 17 | +If you don't have it already, you can [get `rustup`][install] from the appropriate page on our website, |
| 18 | +and check out the [detailed release notes for 1.35.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-1350-2019-05-23 |
| 22 | + |
| 23 | +## What's in 1.35.0 stable |
| 24 | + |
| 25 | +The highlight of this release is the implementation of the `FnOnce`, `FnMut`, |
| 26 | +and `Fn` closure traits for `Box<dyn FnOnce>`, `Box<dyn FnMut>`, and `Box<dyn Fn>` respectively. |
| 27 | +Additionally, closures may now be coerced to unsafe function pointers. |
| 28 | +The `dbg!` macro introduced in [Rust 1.32.0] can now also be called without arguments. |
| 29 | +Moreover, there were a number of standard library stabilizations. |
| 30 | +Read on for a few highlights, or see the [detailed release notes][notes] for additional information. |
| 31 | + |
| 32 | +### `Fn*` closure traits implemented for `Box<dyn Fn*>` |
| 33 | + |
| 34 | +[fn-pr]: https://github.com/rust-lang/rust/pull/55431 |
| 35 | +[`FnBox`]: https://doc.rust-lang.org/1.34.0/std/boxed/trait.FnBox.html |
| 36 | +[unsized locals]: https://doc.rust-lang.org/nightly/unstable-book/language-features/unsized-locals.html |
| 37 | + |
| 38 | +In Rust 1.35.0, the `FnOnce`, `FnMut`, and the `Fn` traits [are now implemented][fn-pr] for `Box<dyn FnOnce>`, |
| 39 | +`Box<dyn FnMut>`, and `Box<dyn Fn>` respectively. |
| 40 | + |
| 41 | +Previously, if you wanted to call the function stored in a boxed closure, you had to use [`FnBox`]. |
| 42 | +This was because instances of `Box<dyn FnOnce>` and friends did not implement the respective `Fn*` traits. |
| 43 | +This also meant that it was not possible to pass boxed functions to code expecting an implementor of a `Fn` trait, |
| 44 | +and you had to create temporary closures to pass them down. |
| 45 | + |
| 46 | +This was ultimately due to a limitation in the compiler's ability to reason about such implementations, |
| 47 | +which has since been fixed with the introduction of [unsized locals]. |
| 48 | + |
| 49 | +With this release, you can now use boxed functions in places that expect items implementing a function trait. |
| 50 | + |
| 51 | +The following code now works: |
| 52 | + |
| 53 | +```rust |
| 54 | +fn foo(x: Box<dyn Fn(u8) -> u8>) -> Vec<u8> { |
| 55 | + vec![1, 2, 3, 4].into_iter().map(x).collect() |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +Furthermore, you can now directly call `Box<dyn FnOnce>` objects: |
| 60 | + |
| 61 | +```rust |
| 62 | +fn foo(x: Box<dyn FnOnce()>) { |
| 63 | + x() |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +### Coercing closures to `unsafe fn` pointers |
| 68 | + |
| 69 | +[Rust 1.19.0]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html |
| 70 | +[`RawWakerVTable`]: https://doc.rust-lang.org/beta/std/task/struct.RawWakerVTable.html |
| 71 | + |
| 72 | +Since [Rust 1.19.0], it has been possible to coerce closures that do not capture from their environment into function pointers. |
| 73 | +For example, you may write: |
| 74 | + |
| 75 | +```rust |
| 76 | +fn twice(x: u8, f: fn(u8) -> u8) -> u8 { |
| 77 | + f(f(x)) |
| 78 | +} |
| 79 | + |
| 80 | +fn main() { |
| 81 | + assert_eq!(42, twice(0, |x| x + 21)); |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +This has however not extended to `unsafe` function pointers. |
| 86 | +With this release of Rust, you may now do so. For example: |
| 87 | + |
| 88 | +```rust |
| 89 | +/// The safety invariants are those of the `unsafe fn` pointer passed. |
| 90 | +unsafe fn call_unsafe_fn_ptr(f: unsafe fn()) { |
| 91 | + f() |
| 92 | +} |
| 93 | + |
| 94 | +fn main() { |
| 95 | + // SAFETY: There are no invariants. |
| 96 | + // The closure is statically prevented from doing unsafe things. |
| 97 | + unsafe { |
| 98 | + call_unsafe_fn_ptr(|| { |
| 99 | + dbg!(); |
| 100 | + }); |
| 101 | + } |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +### Calling `dbg!()` with no argument |
| 106 | + |
| 107 | +[Rust 1.32.0]: https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#the-dbg-macro |
| 108 | +[the `dbg!` macro]: https://doc.rust-lang.org/std/macro.dbg.html |
| 109 | + |
| 110 | +For the benefit of all the occasional and frequent "print debuggers" out there, |
| 111 | +[Rust 1.32.0] saw the release of [the `dbg!` macro]. |
| 112 | +To recap, the macro allows you to quickly inspect the value of some expression with context. |
| 113 | +For example, when running: |
| 114 | + |
| 115 | +```rust |
| 116 | +fn main() { |
| 117 | + let mut x = 0; |
| 118 | + |
| 119 | + if dbg!(x == 1) { |
| 120 | + x += 1; |
| 121 | + } |
| 122 | + |
| 123 | + dbg!(x); |
| 124 | +} |
| 125 | +``` |
| 126 | + |
| 127 | +...you would see: |
| 128 | + |
| 129 | +``` |
| 130 | +[src/main.rs:4] x == 1 = false |
| 131 | +[src/main.rs:8] x = 0 |
| 132 | +``` |
| 133 | + |
| 134 | + |
| 135 | +As seen in the previous section, where the higher order function `call_unsafe_fn_ptr` is called, |
| 136 | +you may now also call `dbg!` without passing any arguments. |
| 137 | +This is useful when tracing what branches your application takes. |
| 138 | +For example, with: |
| 139 | + |
| 140 | +```rust |
| 141 | +fn main() { |
| 142 | + let condition = true; |
| 143 | + |
| 144 | + if condition { |
| 145 | + dbg!(); |
| 146 | + } |
| 147 | +} |
| 148 | +``` |
| 149 | + |
| 150 | +...you would see: |
| 151 | + |
| 152 | +``` |
| 153 | +[src/main.rs:5] |
| 154 | +``` |
| 155 | + |
| 156 | +### Library stabilizations |
| 157 | + |
| 158 | +[`f32::copysign`]: https://doc.rust-lang.org/std/primitive.f32.html#method.copysign |
| 159 | +[`f64::copysign`]: https://doc.rust-lang.org/std/primitive.f64.html#method.copysign |
| 160 | +[`RefCell::replace_with`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace_with |
| 161 | +[`Ref::map_split`]: https://doc.rust-lang.org/std/cell/struct.Ref.html#method.map_split |
| 162 | +[`RefMut::map_split`]: https://doc.rust-lang.org/std/cell/struct.RefMut.html#method.map_split |
| 163 | +[`ptr::hash`]: https://doc.rust-lang.org/std/ptr/fn.hash.html |
| 164 | +[`Range::contains`]: https://doc.rust-lang.org/std/ops/struct.Range.html#method.contains |
| 165 | +[`RangeFrom::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeFrom.html#method.contains |
| 166 | +[`RangeTo::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeTo.html#method.contains |
| 167 | +[`RangeInclusive::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.contains |
| 168 | +[`RangeToInclusive::contains`]: https://doc.rust-lang.org/std/ops/struct.RangeToInclusive.html#method.contains |
| 169 | +[`Option::copied`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.copied |
| 170 | + |
| 171 | +In 1.35.0, a number of APIs have become stable. |
| 172 | + |
| 173 | +In addition, some implementations were added and other changes occured as well. |
| 174 | +See the [detailed release notes][notes] for more details. |
| 175 | + |
| 176 | +#### Copy the sign of a floating point number onto another |
| 177 | + |
| 178 | +[`f32`]: https://doc.rust-lang.org/std/primitive.f32.html |
| 179 | +[`f64`]: https://doc.rust-lang.org/std/primitive.f64.html |
| 180 | + |
| 181 | +With this release, new methods `copysign` have been added to the floating point primitive types [`f32`] and [`f64`]: |
| 182 | + |
| 183 | +- [`f32::copysign`] |
| 184 | +- [`f64::copysign`] |
| 185 | + |
| 186 | +As the name suggests, you can use these to copy the sign of one number onto another. For example: |
| 187 | + |
| 188 | +```rust |
| 189 | +fn main() { |
| 190 | + assert_eq!(3.5_f32.copysign(-0.42), -3.5); |
| 191 | +} |
| 192 | +``` |
| 193 | + |
| 194 | +#### Check whether a `Range` `contains` a value |
| 195 | + |
| 196 | +Rust 1.35.0 contains a few freshly minted methods on the `Range` types: |
| 197 | + |
| 198 | +- [`Range::contains`] |
| 199 | +- [`RangeFrom::contains`] |
| 200 | +- [`RangeTo::contains`] |
| 201 | +- [`RangeInclusive::contains`] |
| 202 | +- [`RangeToInclusive::contains`] |
| 203 | + |
| 204 | +With these, you can easily check whether a given value exists in a range. For example, you may write: |
| 205 | + |
| 206 | +```rust |
| 207 | +fn main() { |
| 208 | + if (0..=10).contains(&5) { |
| 209 | + println!("Five is included in zero to ten."); |
| 210 | + } |
| 211 | +} |
| 212 | +``` |
| 213 | + |
| 214 | +#### Map and split a borrowed `RefCell` value in two |
| 215 | + |
| 216 | +With Rust 1.35.0, you can now map and split the borrowed value of a `RefCell` into multiple borrows for different components of the borrowed data: |
| 217 | + |
| 218 | +- [`Ref::map_split`] |
| 219 | +- [`RefMut::map_split`] |
| 220 | + |
| 221 | +#### Replace the value of a `RefCell` through a closure |
| 222 | + |
| 223 | +This release introduces a convenience method `replace_with` on `RefCell`: |
| 224 | + |
| 225 | +- [`RefCell::replace_with`] |
| 226 | + |
| 227 | +With it, you can more ergonomically map and replace the current value of the cell and get back the old value as a result. |
| 228 | + |
| 229 | +#### Hash a pointer or reference by address, not value |
| 230 | + |
| 231 | +In this release, we have introduced: |
| 232 | + |
| 233 | +- [`ptr::hash`] |
| 234 | + |
| 235 | +This function takes a raw pointer and hashes it. Using `ptr::hash`, |
| 236 | +you can avoid hashing the pointed-to value of a reference and instead hash the address. |
| 237 | + |
| 238 | +#### Copy the contents of an `Option<&T>` |
| 239 | + |
| 240 | +From the very beginning with Rust 1.0.0, |
| 241 | +the methods `Option::cloned` for `Option<&T>` and `Option<&mut T>` have allowed you to clone the contents in case of `Some(_)`. |
| 242 | +However, cloning can sometimes be an expensive operation and the methods `opt.cloned()` provided no hints to that effect. |
| 243 | + |
| 244 | +With this release of Rust, we introduced: |
| 245 | + |
| 246 | +- [`Option::copied`] for both `Option<&T>` and `Option<&mut T>` |
| 247 | + |
| 248 | +The functionality of `opt.copied()` is the same as for `opt.cloned()`. |
| 249 | +However, calling the method requires that `T: Copy`. |
| 250 | +Using this method, you can make sure that code stops compiling should `T` no longer implements `Copy`. |
| 251 | + |
| 252 | +### Changes in Clippy |
| 253 | + |
| 254 | +[relnotes-clippy]: |
| 255 | +https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-135-beta |
| 256 | + |
| 257 | +[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds |
| 258 | + |
| 259 | +[split_lint]: https://github.com/rust-lang/rust-clippy/pull/4101 |
| 260 | + |
| 261 | +In this release of Rust, |
| 262 | +Clippy (a collection of lints to catch common mistakes and improve your Rust code) added a new lint [`drop_bounds`]. |
| 263 | +This lint triggers when you add a bound `T: Drop` to a generic function. For example: |
| 264 | + |
| 265 | +```rust |
| 266 | +fn foo<T: Drop>(x: T) {} |
| 267 | +``` |
| 268 | + |
| 269 | +Having a bound `T: Drop` is almost always a mistake as it excludes types, |
| 270 | +such as `u8`, which have trivial drop-glues. |
| 271 | +Moreover, `T: Drop` does not account for types like `String` not having interesting destructor behavior directly but rather as a result of embedding types, |
| 272 | +such as `Vec<u8>`, that do. |
| 273 | + |
| 274 | +In addition to [`drop_bounds`], |
| 275 | +this release of Clippy [split][split_lint] the lint`redundant_closure` into `redundant_closure` and `redundant_closure_for_method_calls`. |
| 276 | + |
| 277 | +See the [detailed release notes for Clippy][relnotes-clippy] for more details. |
| 278 | + |
| 279 | +### Changes in Cargo |
| 280 | + |
| 281 | +[relnotes-cargo]: |
| 282 | +https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-135-2019-05-23 |
| 283 | + |
| 284 | +See the [detailed release notes for Cargo][relnotes-cargo] for more details. |
| 285 | + |
| 286 | +## Contributors to 1.35.0 |
| 287 | + |
| 288 | +Many people came together to create Rust 1.35.0. |
| 289 | +We couldn't have done it without all of you. |
| 290 | +[Thanks!](https://thanks.rust-lang.org/rust/1.35.0/) |
0 commit comments