Skip to content

Commit c693897

Browse files
committed
Stabilized APIs and Mismatched lifetime syntaxes lint
1 parent 1ebc7da commit c693897

File tree

1 file changed

+100
-2
lines changed

1 file changed

+100
-2
lines changed

content/Rust-1.89.0.md

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,81 @@ pub const MY_BITSET: [bool; _] = make_bitset::<10>();
4545

4646
### Mismatched lifetimes syntax lint
4747

48-
TC/LANG to write this
48+
### Mismatched lifetime syntaxes lint
49+
50+
[Lifetime elision][elision] in function signatures is an ergonomic aspect of the Rust language, but it can also be a stumbling point for newcomers and experts alike. This is especially true when lifetimes are inferred in types where it isn't syntactically obvious that a lifetime is even present:
51+
52+
```rust
53+
// The returned type `std::slice::Iter` has a lifetime,
54+
// but there's no visual indication of that.
55+
//
56+
// Lifetime elision infers the lifetime of the return
57+
// value to be the same as the argument `scores`.
58+
fn items(scores: &[u8]) -> std::slice::Iter<u8> {
59+
scores.iter()
60+
}
61+
```
62+
63+
Code like this will now produce a warning by default:
64+
65+
```text
66+
warning: hiding a lifetime that's elided elsewhere is confusing
67+
--> src/lib.rs:1:18
68+
|
69+
1 | fn items(scores: &[u8]) -> std::slice::Iter<u8> {
70+
| ^^^^^ -------------------- the same lifetime is hidden here
71+
| |
72+
| the lifetime is elided here
73+
|
74+
= help: the same lifetime is referred to in inconsistent ways, making the signature confusing
75+
= note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
76+
help: use `'_` for type paths
77+
|
78+
1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> {
79+
| +++
80+
```
81+
82+
We [first attempted][elided_lifetime_in_path] to improve this situation back in 2018 as part of the [`rust_2018_idioms`][2018-by-default] lint group, but [strong feedback][bevy] about the `elided_lifetimes_in_paths` lint showed that it was too blunt of a hammer as it warns about lifetimes which don't matter to understand the function:
83+
84+
```rust
85+
use std::fmt;
86+
87+
struct Greeting;
88+
89+
impl fmt::Display for Greeting {
90+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91+
// -----^^^^^^^^^ expected lifetime parameter
92+
// Knowing that `Formatter` has a lifetime does not help the programmer
93+
"howdy".fmt(f)
94+
}
95+
}
96+
```
97+
98+
We then realized that the confusion we want to eliminate occurs when both
99+
100+
1. lifetime elision inference rules *connect* an input lifetime to an output lifetime
101+
2. it's not syntactically obvious that a lifetime exists
102+
103+
There are two pieces of Rust syntax that indicate that a lifetime exists: `&` and `'`, with `'` being subdivided into the inferred lifetime `'_` and named lifetimes `'a`. When a type uses a named lifetime, lifetime elision will not infer a lifetime for that type. Using these criteria, we can construct three groups:
104+
105+
| Self-evident it has a lifetime | Allow lifetime elision to infer a lifetime | Examples |
106+
|--------------------------------|--------------------------------------------|---------------------------------------|
107+
| No | Yes | `ContainsLifetime` |
108+
| Yes | Yes | `&T`, `&'_ T`, `ContainsLifetime<'_>` |
109+
| Yes | No | `&'a T`, `ContainsLifetime<'a>` |
110+
111+
The `mismatched_lifetime_syntaxes` lint checks that the inputs and outputs of a function belong to the same group. For the initial motivating example above, `&[u8]` falls into the second group while `std::slice::Iter<u8>` falls into the first group. We say that the lifetimes in the first group are *hidden*.
112+
113+
Because the input and output lifetimes belong to different groups, the lint will warn about this function, reducing confusion about when a value has a meaningful lifetime that isn't visually obvious.
114+
115+
The `mismatched_lifetime_syntaxes` lint supersedes the `elided_named_lifetimes` lint, which did something similar for named lifetimes specifically.
116+
117+
Future work on the `elided_lifetimes_in_paths` lint intends to split it into more focused sub-lints with an eye to warning about a subset of them eventually.
118+
119+
[elision]: https://doc.rust-lang.org/1.89/book/ch10-03-lifetime-syntax.html#lifetime-elision
120+
[elided_lifetime_in_path]: https://github.com/rust-lang/rust/pull/46254
121+
[2018-by-default]: https://github.com/rust-lang/rust/issues/54910
122+
[bevy]: https://github.com/rust-lang/rust/issues/131725
49123

50124
### More x86 target features
51125

@@ -67,7 +141,31 @@ Refer to Rust’s [platform support page][platform_support_page] for more inform
67141

68142
### Stabilized APIs
69143

70-
TODO
144+
- [`NonZero<char>`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html)
145+
- Many intrinsics for x86, not enumerated here
146+
- [AVX512 intrinsics](https://github.com/rust-lang/rust/issues/111137)
147+
- [`SHA512`, `SM3` and `SM4` intrinsics](https://github.com/rust-lang/rust/issues/126624)
148+
- [`File::lock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.lock)
149+
- [`File::lock_shared`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.lock_shared)
150+
- [`File::try_lock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.try_lock)
151+
- [`File::try_lock_shared`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.try_lock_shared)
152+
- [`File::unlock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.unlock)
153+
- [`NonNull::from_ref`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.from_ref)
154+
- [`NonNull::from_mut`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.from_mut)
155+
- [`NonNull::without_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.without_provenance)
156+
- [`NonNull::with_exposed_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.with_exposed_provenance)
157+
- [`NonNull::expose_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.expose_provenance)
158+
- [`OsString::leak`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.leak)
159+
- [`PathBuf::leak`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.leak)
160+
- [`Result::flatten`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.flatten)
161+
- [`std::os::linux::net::TcpStreamExt::quickack`](https://doc.rust-lang.org/stable/std/os/linux/net/trait.TcpStreamExt.html#tymethod.quickack)
162+
- [`std::os::linux::net::TcpStreamExt::set_quickack`](https://doc.rust-lang.org/stable/std/os/linux/net/trait.TcpStreamExt.html#tymethod.set_quickack)
163+
164+
These previously stable APIs are now stable in const contexts:
165+
166+
- [`<[T; N]>::as_mut_slice`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.as_mut_slice)
167+
- [`<[u8]>::eq_ignore_ascii_case`](https://doc.rust-lang.org/stable/std/primitive.slice.html#impl-%5Bu8%5D/method.eq_ignore_ascii_case)
168+
- [`str::eq_ignore_ascii_case`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-str/method.eq_ignore_ascii_case)
71169

72170
### Other changes
73171

0 commit comments

Comments
 (0)