You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: posts/2024-10-17-Rust-1.82.0.md
+77Lines changed: 77 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,6 +57,83 @@ The Rust target `aarch64-apple-darwin` for macOS on 64-bit ARM (M1-family or lat
57
57
58
58
[The targets](https://doc.rust-lang.org/nightly/rustc/platform-support/apple-ios-macabi.html) are now tier 2, and can be downloaded with `rustup target add aarch64-apple-ios-macabi x86_64-apple-ios-macabi`, so now is an excellent time to update your CI pipeline to test that your code also runs in iOS-like environments.
59
59
60
+
### Precise capturing `use<..>` syntax
61
+
62
+
Rust now supports `use<..>` syntax within certain impl Trait bounds to control which generic lifetime parameters are captured.
63
+
64
+
Return-position impl Trait (RPIT) types in Rust *capture* certain generic parameters. Capturing a generic parameter allows that parameter to be used in the hidden type. That in turn affects borrow checking.
65
+
66
+
In Rust 2021 and earlier editions, lifetime parameters are not captured in opaque types on bare functions and on functions and methods of inherent impls unless those lifetime parameters are mentioned syntactically in the opaque type. E.g., this is an error:
67
+
68
+
```rust
69
+
//@ edition: 2021
70
+
fnf(x:&()) ->implSized { x }
71
+
```
72
+
73
+
```
74
+
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
75
+
--> src/main.rs:1:30
76
+
|
77
+
1 | fn f(x: &()) -> impl Sized { x }
78
+
| --- ---------- ^
79
+
| | |
80
+
| | opaque type defined here
81
+
| hidden type `&()` captures the anonymous lifetime defined here
82
+
|
83
+
help: add a `use<...>` bound to explicitly capture `'_`
84
+
|
85
+
1 | fn f(x: &()) -> impl Sized + use<'_> { x }
86
+
| +++++++++
87
+
```
88
+
89
+
With the new `use<..>` syntax, we can fix this, as suggested in the error, by writing:
90
+
91
+
```rust
92
+
fnf(x:&()) ->implSized+use<'_> { x }
93
+
```
94
+
95
+
Previously, correctly fixing this class of error required defining a dummy trait, conventionally called `Captures`, and using it as follows:
96
+
97
+
```rust
98
+
traitCaptures<T:?Sized> {}
99
+
impl<T:?Sized, U:?Sized> Captures<T> forU {}
100
+
101
+
fnf(x:&()) ->implSized+Captures<&'_ ()> { x }
102
+
```
103
+
104
+
That was called ["the `Captures` trick"](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick), and it was a bit baroque and subtle. It's no longer needed.
105
+
106
+
There was a less correct way but more convenient way to fix this that was often used called ["the outlives trick"](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-outlives-trick). The compiler even previously suggested doing this. That trick looked like this:
107
+
108
+
```rust
109
+
fnf(x:&()) ->implSized+ '_ { x }
110
+
```
111
+
112
+
In this simple case, the trick is exactly equivalent to `+ use<'_>` for subtle reasons explained in [RFC 3498](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md). However, in real life cases, this overconstrains the bounds on the returned opaque type, leading to problems. For example, consider this code, which is inspired by a real case in the Rust compiler:
113
+
114
+
```rust
115
+
structCtx<'cx>(&'cxu8);
116
+
117
+
fnf<'cx, 'a>(
118
+
cx:Ctx<'cx>,
119
+
x:&'au8,
120
+
) ->implIterator<Item=&'au8> + 'cx {
121
+
core::iter::once_with(move|| {
122
+
eprintln!("LOG: {}", cx.0);
123
+
x
124
+
})
125
+
//~^ ERROR lifetime may not live long enough
126
+
}
127
+
```
128
+
129
+
We can't remove the `+ 'cx`, since the lifetime is used in the hidden type and so must be captured. Neither can we add a bound of `'a: 'cx`, since these lifetimes are not actually related and it won't in general be true that `'a` outlives `'cx`. If we write `+ use<'cx, 'a>` instead, however, this will work and have the correct bounds.
130
+
131
+
There are some limitations to what we're stabilizing today. The `use<..>` syntax cannot currently appear within traits or within trait impls (but note that there, in-scope lifetime parameters are already captured by default), and it must list all in-scope generic type and const parameters. We hope to lift these restrictions over time.
132
+
133
+
Note that in Rust 2024, the examples above will "just work" without needing `use<..>` syntax (or any tricks). This is because in the new edition, opaque types will automatically capture all lifetime parameters in scope. This is a better default, and we've seen a lot of evidence about how this cleans up code. In Rust 2024, `use<..>` syntax will serve as an important way of opting-out of that default.
134
+
135
+
For more details about `use<..>` syntax, capturing, and how this applies to Rust 2024, see the ["RPIT lifetime capture rules"](https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html) chapter of the edition guide. For details about the overall direction, see our recent blog post, ["Changes to `impl Trait` in Rust 2024"](https://blog.rust-lang.org/2024/09/05/impl-trait-capture-rules.html).
136
+
60
137
### Native syntax for creating a raw pointer
61
138
62
139
Unsafe code sometimes has to deal with pointers that may dangle, may be misaligned, or may not point to valid data. A common case where this comes up are `repr(packed)` structs. In such a case, it is important to avoid creating a reference, as that would cause undefined behavior. This means the usual `&` and `&mut` operators cannot be used, as those create a reference -- even if the reference is immediately cast to a raw pointer, it's too late to avoid the undefined behavior.
0 commit comments