Description
Code
pub struct Foo<'a> {
// `Cow` just used as a convenient lifetime-bearing type
pub foo: &'a mut std::borrow::Cow<'a, str>
}
Current output
No output
Desired output
error: this mutable reference will borrow its referent forever
3 | pub foo: &'a mut std::borrow::Cow<'a, str>
| -- -- this use of `'a` requires it to outlive all values of type `std::borrow::Cow<'a, str>`
| |
| this use of `'a` requires the `std::borrow::Cow<'a, str>` to be exclusively borrowed until the end of `'a`
|
= help: this type is valid, but almost certainly incorrect
= help: use two distinct lifetime parameters instead:
<suggestions to change either the first or second to a newly introduced parameter>
= note: `#[deny(perpetual_mut_borrow)]` on by default
Rationale and extra context
&'a mut T<'a>
is a fairly common beginner mistake. The compiler can even suggest it as an added lifetime annotation if one tries to construct a self-referential struct. It's not at all obvious that this is a mistake (especially as &'a T<'a>
is valid and entirely suitable for many applications), and people become quite confused due to the additional, not obviously related, lifetime and drop errors that then result. Therefore, I believe it is worth having the compiler lint this case.
I propose that it be a deny-by-default lint so that
- it is more prominent than a default warning and indicates “this is so wrong that you need to stop and reassess”, but
- if someone does have a situation where this is actually the correct lifetime (perhaps they truly intend to make a self-referential struct and use it inside an infinite loop), they can suppress the lint.
Other cases
There may be some subtlety in applying the lint to arbitrary types. My hope is that a simple structural/syntactic rule is sufficiently precise to be helpful: if the same lifetime name appears inside an &mut
as the &mut
's own lifetime, then lint. But if it is feasible to directly check for "this reference is required to outlive-or-equal its referent" then that would more precisely identify the problem, including accounting for outlives bounds between two lifetimes that have the same effect.
Rust Version
rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-apple-darwin
release: 1.75.0
LLVM version: 17.0.6