pub static TAIL_EXPR_DROP_ORDER: &Lint
Expand description
The tail_expr_drop_order
lint looks for those values generated at the tail expression location, that of type
with a significant Drop
implementation, such as locks.
In case there are also local variables of type with significant Drop
implementation as well,
this lint warns you of a potential transposition in the drop order.
Your discretion on the new drop order introduced by Edition 2024 is required.
§Example
#![feature(shorter_tail_lifetimes)]
#![warn(tail_expr_drop_order)]
struct Droppy(i32);
impl Droppy {
fn get(&self) -> i32 {
self.0
}
}
impl Drop for Droppy {
fn drop(&mut self) {
// This is a custom destructor and it induces side-effects that is observable
// especially when the drop order at a tail expression changes.
println!("loud drop {}", self.0);
}
}
fn edition_2024() -> i32 {
let another_droppy = Droppy(0);
Droppy(1).get()
}
fn main() {
edition_2024();
}
{{produces}}
§Explanation
In tail expression of blocks or function bodies,
values of type with significant Drop
implementation has an ill-specified drop order
before Edition 2024 so that they are dropped only after dropping local variables.
Edition 2024 introduces a new rule with drop orders for them,
so that they are dropped first before dropping local variables.
A significant Drop::drop
destructor here refers to an explicit, arbitrary
implementation of the Drop
trait on the type, with exceptions including Vec
,
Box
, Rc
, BTreeMap
and HashMap
that are marked by the compiler otherwise
so long that the generic types have no significant destructor recursively.
In other words, a type has a significant drop destructor when it has a Drop
implementation
or its destructor invokes a significant destructor on a type.
Since we cannot completely reason about the change by just inspecting the existence of
a significant destructor, this lint remains only a suggestion and is set to allow
by default.
This lint only points out the issue with Droppy
, which will be dropped before another_droppy
does in Edition 2024.
No fix will be proposed by this lint.
However, the most probable fix is to hoist Droppy
into its own local variable binding.
struct Droppy(i32);
impl Droppy {
fn get(&self) -> i32 {
self.0
}
}
fn edition_2024() -> i32 {
let value = Droppy(0);
let another_droppy = Droppy(1);
value.get()
}