Print out destructor
This commit is contained in:
parent
ac91805f31
commit
864cca80b0
11 changed files with 425 additions and 186 deletions
|
@ -3916,6 +3916,7 @@ dependencies = [
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
"rustc_trait_selection",
|
"rustc_trait_selection",
|
||||||
"rustc_type_ir",
|
"rustc_type_ir",
|
||||||
|
"smallvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
"unicode-security",
|
"unicode-security",
|
||||||
]
|
]
|
||||||
|
|
|
@ -24,6 +24,7 @@ rustc_span = { path = "../rustc_span" }
|
||||||
rustc_target = { path = "../rustc_target" }
|
rustc_target = { path = "../rustc_target" }
|
||||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||||
rustc_type_ir = { path = "../rustc_type_ir" }
|
rustc_type_ir = { path = "../rustc_type_ir" }
|
||||||
|
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
unicode-security = "0.1.0"
|
unicode-security = "0.1.0"
|
||||||
# tidy-alphabetical-end
|
# tidy-alphabetical-end
|
||||||
|
|
|
@ -333,6 +333,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
|
||||||
*[other] {" "}{$identifier_type}
|
*[other] {" "}{$identifier_type}
|
||||||
} Unicode general security profile
|
} Unicode general security profile
|
||||||
|
|
||||||
|
lint_if_let_dtor = {$dtor_kind ->
|
||||||
|
[dyn] value may invoke a custom destructor because it contains a trait object
|
||||||
|
*[concrete] value invokes this custom destructor
|
||||||
|
}
|
||||||
|
|
||||||
lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024
|
lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024
|
||||||
.label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
.label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
||||||
.help = the value is now dropped here in Edition 2024
|
.help = the value is now dropped here in Edition 2024
|
||||||
|
|
|
@ -7,13 +7,17 @@ use rustc_errors::{
|
||||||
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
|
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
|
||||||
};
|
};
|
||||||
use rustc_hir::{self as hir, HirIdSet};
|
use rustc_hir::{self as hir, HirIdSet};
|
||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
use rustc_middle::ty::adjustment::Adjust;
|
use rustc_middle::ty::adjustment::Adjust;
|
||||||
|
use rustc_middle::ty::significant_drop_order::{
|
||||||
|
extract_component_with_significant_dtor, ty_dtor_span,
|
||||||
|
};
|
||||||
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
|
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
|
||||||
use rustc_session::{declare_lint, impl_lint_pass};
|
use rustc_session::{declare_lint, impl_lint_pass};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{LateContext, LateLintPass};
|
use crate::{LateContext, LateLintPass};
|
||||||
|
|
||||||
|
@ -130,6 +134,7 @@ impl IfLetRescope {
|
||||||
hir::ExprKind::If(_cond, _conseq, Some(alt)) => alt.span.shrink_to_hi(),
|
hir::ExprKind::If(_cond, _conseq, Some(alt)) => alt.span.shrink_to_hi(),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
let mut seen_dyn = false;
|
||||||
let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr);
|
let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr);
|
||||||
let mut significant_droppers = vec![];
|
let mut significant_droppers = vec![];
|
||||||
let mut lifetime_ends = vec![];
|
let mut lifetime_ends = vec![];
|
||||||
|
@ -137,6 +142,7 @@ impl IfLetRescope {
|
||||||
let mut alt_heads = vec![];
|
let mut alt_heads = vec![];
|
||||||
let mut match_heads = vec![];
|
let mut match_heads = vec![];
|
||||||
let mut consequent_heads = vec![];
|
let mut consequent_heads = vec![];
|
||||||
|
let mut destructors = vec![];
|
||||||
let mut first_if_to_lint = None;
|
let mut first_if_to_lint = None;
|
||||||
let mut first_if_to_rewrite = false;
|
let mut first_if_to_rewrite = false;
|
||||||
let mut empty_alt = false;
|
let mut empty_alt = false;
|
||||||
|
@ -160,11 +166,25 @@ impl IfLetRescope {
|
||||||
let before_conseq = conseq.span.shrink_to_lo();
|
let before_conseq = conseq.span.shrink_to_lo();
|
||||||
let lifetime_end = source_map.end_point(conseq.span);
|
let lifetime_end = source_map.end_point(conseq.span);
|
||||||
|
|
||||||
if let ControlFlow::Break(significant_dropper) =
|
if let ControlFlow::Break((drop_span, drop_tys)) =
|
||||||
(FindSignificantDropper { cx }).check_if_let_scrutinee(init)
|
(FindSignificantDropper { cx }).check_if_let_scrutinee(init)
|
||||||
{
|
{
|
||||||
|
destructors.extend(drop_tys.into_iter().filter_map(|ty| {
|
||||||
|
if let Some(span) = ty_dtor_span(tcx, ty) {
|
||||||
|
Some(DestructorLabel { span, dtor_kind: "concrete" })
|
||||||
|
} else if matches!(ty.kind(), ty::Dynamic(..)) {
|
||||||
|
if seen_dyn {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
seen_dyn = true;
|
||||||
|
Some(DestructorLabel { span: DUMMY_SP, dtor_kind: "dyn" })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}));
|
||||||
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
|
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
|
||||||
significant_droppers.push(significant_dropper);
|
significant_droppers.push(drop_span);
|
||||||
lifetime_ends.push(lifetime_end);
|
lifetime_ends.push(lifetime_end);
|
||||||
if ty_ascription.is_some()
|
if ty_ascription.is_some()
|
||||||
|| !expr.span.can_be_used_for_suggestions()
|
|| !expr.span.can_be_used_for_suggestions()
|
||||||
|
@ -227,6 +247,7 @@ impl IfLetRescope {
|
||||||
hir_id,
|
hir_id,
|
||||||
span,
|
span,
|
||||||
IfLetRescopeLint {
|
IfLetRescopeLint {
|
||||||
|
destructors,
|
||||||
significant_droppers,
|
significant_droppers,
|
||||||
lifetime_ends,
|
lifetime_ends,
|
||||||
rewrite: first_if_to_rewrite.then_some(IfLetRescopeRewrite {
|
rewrite: first_if_to_rewrite.then_some(IfLetRescopeRewrite {
|
||||||
|
@ -288,6 +309,8 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_if_let_rescope)]
|
#[diag(lint_if_let_rescope)]
|
||||||
struct IfLetRescopeLint {
|
struct IfLetRescopeLint {
|
||||||
|
#[subdiagnostic]
|
||||||
|
destructors: Vec<DestructorLabel>,
|
||||||
#[label]
|
#[label]
|
||||||
significant_droppers: Vec<Span>,
|
significant_droppers: Vec<Span>,
|
||||||
#[help]
|
#[help]
|
||||||
|
@ -347,6 +370,14 @@ impl Subdiagnostic for IfLetRescopeRewrite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(lint_if_let_dtor)]
|
||||||
|
struct DestructorLabel {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
dtor_kind: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
struct AltHead(Span);
|
struct AltHead(Span);
|
||||||
|
|
||||||
struct ConsequentRewrite {
|
struct ConsequentRewrite {
|
||||||
|
@ -374,7 +405,10 @@ impl<'tcx> FindSignificantDropper<'_, 'tcx> {
|
||||||
/// of the scrutinee itself, and also recurses into the expression to find any ref
|
/// of the scrutinee itself, and also recurses into the expression to find any ref
|
||||||
/// exprs (or autoref) which would promote temporaries that would be scoped to the
|
/// exprs (or autoref) which would promote temporaries that would be scoped to the
|
||||||
/// end of this `if`.
|
/// end of this `if`.
|
||||||
fn check_if_let_scrutinee(&mut self, init: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
|
fn check_if_let_scrutinee(
|
||||||
|
&mut self,
|
||||||
|
init: &'tcx hir::Expr<'tcx>,
|
||||||
|
) -> ControlFlow<(Span, SmallVec<[Ty<'tcx>; 4]>)> {
|
||||||
self.check_promoted_temp_with_drop(init)?;
|
self.check_promoted_temp_with_drop(init)?;
|
||||||
self.visit_expr(init)
|
self.visit_expr(init)
|
||||||
}
|
}
|
||||||
|
@ -385,28 +419,35 @@ impl<'tcx> FindSignificantDropper<'_, 'tcx> {
|
||||||
/// An expression is a promoted temporary if it has an addr taken (i.e. `&expr` or autoref)
|
/// An expression is a promoted temporary if it has an addr taken (i.e. `&expr` or autoref)
|
||||||
/// or is the scrutinee of the `if let`, *and* the expression is not a place
|
/// or is the scrutinee of the `if let`, *and* the expression is not a place
|
||||||
/// expr, and it has a significant drop.
|
/// expr, and it has a significant drop.
|
||||||
fn check_promoted_temp_with_drop(&self, expr: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
|
fn check_promoted_temp_with_drop(
|
||||||
if !expr.is_place_expr(|base| {
|
&self,
|
||||||
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
) -> ControlFlow<(Span, SmallVec<[Ty<'tcx>; 4]>)> {
|
||||||
|
if expr.is_place_expr(|base| {
|
||||||
self.cx
|
self.cx
|
||||||
.typeck_results()
|
.typeck_results()
|
||||||
.adjustments()
|
.adjustments()
|
||||||
.get(base.hir_id)
|
.get(base.hir_id)
|
||||||
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
|
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
|
||||||
}) && self
|
}) {
|
||||||
.cx
|
return ControlFlow::Continue(());
|
||||||
.typeck_results()
|
|
||||||
.expr_ty(expr)
|
|
||||||
.has_significant_drop(self.cx.tcx, self.cx.typing_env())
|
|
||||||
{
|
|
||||||
ControlFlow::Break(expr.span)
|
|
||||||
} else {
|
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let drop_tys = extract_component_with_significant_dtor(
|
||||||
|
self.cx.tcx,
|
||||||
|
self.cx.typing_env(),
|
||||||
|
self.cx.typeck_results().expr_ty(expr),
|
||||||
|
);
|
||||||
|
if drop_tys.is_empty() {
|
||||||
|
return ControlFlow::Continue(());
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::Break((expr.span, drop_tys))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> {
|
||||||
type Result = ControlFlow<Span>;
|
type Result = ControlFlow<(Span, SmallVec<[Ty<'tcx>; 4]>)>;
|
||||||
|
|
||||||
fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) -> Self::Result {
|
fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) -> Self::Result {
|
||||||
// Blocks introduce temporary terminating scope for all of its
|
// Blocks introduce temporary terminating scope for all of its
|
||||||
|
|
|
@ -122,6 +122,7 @@ pub mod normalize_erasing_regions;
|
||||||
pub mod pattern;
|
pub mod pattern;
|
||||||
pub mod print;
|
pub mod print;
|
||||||
pub mod relate;
|
pub mod relate;
|
||||||
|
pub mod significant_drop_order;
|
||||||
pub mod trait_def;
|
pub mod trait_def;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
172
compiler/rustc_middle/src/ty/significant_drop_order.rs
Normal file
172
compiler/rustc_middle/src/ty/significant_drop_order.rs
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_data_structures::unord::UnordSet;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_span::Span;
|
||||||
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
|
/// An additional filter to exclude well-known types from the ecosystem
|
||||||
|
/// because their drops are trivial.
|
||||||
|
/// This returns additional types to check if the drops are delegated to those.
|
||||||
|
/// A typical example is `hashbrown::HashMap<K, V>`, whose drop is delegated to `K` and `V`.
|
||||||
|
fn true_significant_drop_ty<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> Option<SmallVec<[Ty<'tcx>; 2]>> {
|
||||||
|
if let ty::Adt(def, args) = ty.kind() {
|
||||||
|
let mut did = def.did();
|
||||||
|
let mut name_rev = vec![];
|
||||||
|
loop {
|
||||||
|
let key = tcx.def_key(did);
|
||||||
|
|
||||||
|
match key.disambiguated_data.data {
|
||||||
|
rustc_hir::definitions::DefPathData::CrateRoot => {
|
||||||
|
name_rev.push(tcx.crate_name(did.krate))
|
||||||
|
}
|
||||||
|
rustc_hir::definitions::DefPathData::TypeNs(symbol) => name_rev.push(symbol),
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
if let Some(parent) = key.parent {
|
||||||
|
did = DefId { krate: did.krate, index: parent };
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let name_str: Vec<_> = name_rev.iter().rev().map(|x| x.as_str()).collect();
|
||||||
|
debug!(?name_str);
|
||||||
|
match name_str[..] {
|
||||||
|
// These are the types from Rust core ecosystem
|
||||||
|
["syn" | "proc_macro2", ..]
|
||||||
|
| ["core" | "std", "task", "LocalWaker" | "Waker"]
|
||||||
|
| ["core" | "std", "task", "wake", "LocalWaker" | "Waker"] => Some(smallvec![]),
|
||||||
|
// These are important types from Rust ecosystem
|
||||||
|
["tracing", "instrument", "Instrumented"] | ["bytes", "Bytes"] => Some(smallvec![]),
|
||||||
|
["hashbrown", "raw", "RawTable" | "RawIntoIter"] => {
|
||||||
|
if let [ty, ..] = &***args
|
||||||
|
&& let Some(ty) = ty.as_type()
|
||||||
|
{
|
||||||
|
Some(smallvec![ty])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
["hashbrown", "raw", "RawDrain"] => {
|
||||||
|
if let [_, ty, ..] = &***args
|
||||||
|
&& let Some(ty) = ty.as_type()
|
||||||
|
{
|
||||||
|
Some(smallvec![ty])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the list of types with a "potentially sigificant" that may be dropped
|
||||||
|
/// by dropping a value of type `ty`.
|
||||||
|
#[instrument(level = "trace", skip(tcx, typing_env))]
|
||||||
|
pub fn extract_component_raw<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
ty_seen: &mut UnordSet<Ty<'tcx>>,
|
||||||
|
) -> SmallVec<[Ty<'tcx>; 4]> {
|
||||||
|
// Droppiness does not depend on regions, so let us erase them.
|
||||||
|
let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
|
||||||
|
|
||||||
|
let tys = tcx.list_significant_drop_tys(typing_env.as_query_input(ty));
|
||||||
|
debug!(?ty, "components");
|
||||||
|
let mut out_tys = smallvec![];
|
||||||
|
for ty in tys {
|
||||||
|
if let Some(tys) = true_significant_drop_ty(tcx, ty) {
|
||||||
|
// Some types can be further opened up because the drop is simply delegated
|
||||||
|
for ty in tys {
|
||||||
|
if ty_seen.insert(ty) {
|
||||||
|
out_tys.extend(extract_component_raw(tcx, typing_env, ty, ty_seen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ty_seen.insert(ty) {
|
||||||
|
out_tys.push(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_tys
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(tcx, typing_env))]
|
||||||
|
pub fn extract_component_with_significant_dtor<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> SmallVec<[Ty<'tcx>; 4]> {
|
||||||
|
let mut tys = extract_component_raw(tcx, typing_env, ty, &mut Default::default());
|
||||||
|
let mut deduplicate = FxHashSet::default();
|
||||||
|
tys.retain(|oty| deduplicate.insert(*oty));
|
||||||
|
tys.into_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the span of the custom destructor of a type
|
||||||
|
/// especially the span of the `impl Drop` header or its entire block
|
||||||
|
/// when we are working with current local crate.
|
||||||
|
#[instrument(level = "trace", skip(tcx))]
|
||||||
|
pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Span> {
|
||||||
|
match ty.kind() {
|
||||||
|
ty::Bool
|
||||||
|
| ty::Char
|
||||||
|
| ty::Int(_)
|
||||||
|
| ty::Uint(_)
|
||||||
|
| ty::Float(_)
|
||||||
|
| ty::Error(_)
|
||||||
|
| ty::Str
|
||||||
|
| ty::Never
|
||||||
|
| ty::RawPtr(_, _)
|
||||||
|
| ty::Ref(_, _, _)
|
||||||
|
| ty::FnPtr(_, _)
|
||||||
|
| ty::Tuple(_)
|
||||||
|
| ty::Dynamic(_, _, _)
|
||||||
|
| ty::Alias(_, _)
|
||||||
|
| ty::Bound(_, _)
|
||||||
|
| ty::Pat(_, _)
|
||||||
|
| ty::Placeholder(_)
|
||||||
|
| ty::Infer(_)
|
||||||
|
| ty::Slice(_)
|
||||||
|
| ty::Array(_, _)
|
||||||
|
| ty::UnsafeBinder(_) => None,
|
||||||
|
|
||||||
|
ty::Adt(adt_def, _) => {
|
||||||
|
let did = adt_def.did();
|
||||||
|
let try_local_did_span = |did: DefId| {
|
||||||
|
if let Some(local) = did.as_local() {
|
||||||
|
tcx.source_span(local)
|
||||||
|
} else {
|
||||||
|
tcx.def_span(did)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dtor = if let Some(dtor) = tcx.adt_destructor(did) {
|
||||||
|
dtor.did
|
||||||
|
} else if let Some(dtor) = tcx.adt_async_destructor(did) {
|
||||||
|
dtor.future
|
||||||
|
} else {
|
||||||
|
return Some(try_local_did_span(did));
|
||||||
|
};
|
||||||
|
let def_key = tcx.def_key(dtor);
|
||||||
|
let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) };
|
||||||
|
let parent_did = DefId { index: parent_index, krate: dtor.krate };
|
||||||
|
Some(try_local_did_span(parent_did))
|
||||||
|
}
|
||||||
|
ty::Coroutine(did, _)
|
||||||
|
| ty::CoroutineWitness(did, _)
|
||||||
|
| ty::CoroutineClosure(did, _)
|
||||||
|
| ty::Closure(did, _)
|
||||||
|
| ty::FnDef(did, _)
|
||||||
|
| ty::Foreign(did) => Some(tcx.def_span(did)),
|
||||||
|
ty::Param(_) => None,
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||||
use rustc_errors::Subdiagnostic;
|
use rustc_errors::Subdiagnostic;
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_index::bit_set::MixedBitSet;
|
use rustc_index::bit_set::MixedBitSet;
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||||
|
@ -15,7 +15,10 @@ use rustc_middle::mir::{
|
||||||
self, BasicBlock, Body, ClearCrossCrate, Local, Location, Place, StatementKind, TerminatorKind,
|
self, BasicBlock, Body, ClearCrossCrate, Local, Location, Place, StatementKind, TerminatorKind,
|
||||||
dump_mir,
|
dump_mir,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::significant_drop_order::{
|
||||||
|
extract_component_with_significant_dtor, ty_dtor_span,
|
||||||
|
};
|
||||||
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
||||||
use rustc_mir_dataflow::{Analysis, MaybeReachable, ResultsCursor};
|
use rustc_mir_dataflow::{Analysis, MaybeReachable, ResultsCursor};
|
||||||
|
@ -23,8 +26,7 @@ use rustc_session::lint::builtin::TAIL_EXPR_DROP_ORDER;
|
||||||
use rustc_session::lint::{self};
|
use rustc_session::lint::{self};
|
||||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||||
use rustc_type_ir::data_structures::IndexMap;
|
use rustc_type_ir::data_structures::IndexMap;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use tracing::debug;
|
||||||
use tracing::{debug, instrument};
|
|
||||||
|
|
||||||
fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool {
|
fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool {
|
||||||
left.local == right.local
|
left.local == right.local
|
||||||
|
@ -155,170 +157,6 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An additional filter to exclude well-known types from the ecosystem
|
|
||||||
/// because their drops are trivial.
|
|
||||||
/// This returns additional types to check if the drops are delegated to those.
|
|
||||||
/// A typical example is `hashbrown::HashMap<K, V>`, whose drop is delegated to `K` and `V`.
|
|
||||||
fn true_significant_drop_ty<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Option<SmallVec<[Ty<'tcx>; 2]>> {
|
|
||||||
if let ty::Adt(def, args) = ty.kind() {
|
|
||||||
let mut did = def.did();
|
|
||||||
let mut name_rev = vec![];
|
|
||||||
loop {
|
|
||||||
let key = tcx.def_key(did);
|
|
||||||
|
|
||||||
match key.disambiguated_data.data {
|
|
||||||
rustc_hir::definitions::DefPathData::CrateRoot => {
|
|
||||||
name_rev.push(tcx.crate_name(did.krate))
|
|
||||||
}
|
|
||||||
rustc_hir::definitions::DefPathData::TypeNs(symbol) => name_rev.push(symbol),
|
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
if let Some(parent) = key.parent {
|
|
||||||
did = DefId { krate: did.krate, index: parent };
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let name_str: Vec<_> = name_rev.iter().rev().map(|x| x.as_str()).collect();
|
|
||||||
debug!(?name_str);
|
|
||||||
match name_str[..] {
|
|
||||||
// These are the types from Rust core ecosystem
|
|
||||||
["syn" | "proc_macro2", ..]
|
|
||||||
| ["core" | "std", "task", "LocalWaker" | "Waker"]
|
|
||||||
| ["core" | "std", "task", "wake", "LocalWaker" | "Waker"] => Some(smallvec![]),
|
|
||||||
// These are important types from Rust ecosystem
|
|
||||||
["tracing", "instrument", "Instrumented"] | ["bytes", "Bytes"] => Some(smallvec![]),
|
|
||||||
["hashbrown", "raw", "RawTable" | "RawIntoIter"] => {
|
|
||||||
if let [ty, ..] = &***args
|
|
||||||
&& let Some(ty) = ty.as_type()
|
|
||||||
{
|
|
||||||
Some(smallvec![ty])
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
["hashbrown", "raw", "RawDrain"] => {
|
|
||||||
if let [_, ty, ..] = &***args
|
|
||||||
&& let Some(ty) = ty.as_type()
|
|
||||||
{
|
|
||||||
Some(smallvec![ty])
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the list of types with a "potentially sigificant" that may be dropped
|
|
||||||
/// by dropping a value of type `ty`.
|
|
||||||
#[instrument(level = "debug", skip(tcx, typing_env))]
|
|
||||||
fn extract_component_raw<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
typing_env: ty::TypingEnv<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
ty_seen: &mut UnordSet<Ty<'tcx>>,
|
|
||||||
) -> SmallVec<[Ty<'tcx>; 4]> {
|
|
||||||
// Droppiness does not depend on regions, so let us erase them.
|
|
||||||
let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
|
|
||||||
|
|
||||||
let tys = tcx.list_significant_drop_tys(typing_env.as_query_input(ty));
|
|
||||||
debug!(?ty, "components");
|
|
||||||
let mut out_tys = smallvec![];
|
|
||||||
for ty in tys {
|
|
||||||
if let Some(tys) = true_significant_drop_ty(tcx, ty) {
|
|
||||||
// Some types can be further opened up because the drop is simply delegated
|
|
||||||
for ty in tys {
|
|
||||||
if ty_seen.insert(ty) {
|
|
||||||
out_tys.extend(extract_component_raw(tcx, typing_env, ty, ty_seen));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ty_seen.insert(ty) {
|
|
||||||
out_tys.push(ty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out_tys
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx, typing_env))]
|
|
||||||
fn extract_component_with_significant_dtor<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
typing_env: ty::TypingEnv<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> SmallVec<[Ty<'tcx>; 4]> {
|
|
||||||
let mut tys = extract_component_raw(tcx, typing_env, ty, &mut Default::default());
|
|
||||||
let mut deduplicate = FxHashSet::default();
|
|
||||||
tys.retain(|oty| deduplicate.insert(*oty));
|
|
||||||
tys.into_iter().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extract the span of the custom destructor of a type
|
|
||||||
/// especially the span of the `impl Drop` header or its entire block
|
|
||||||
/// when we are working with current local crate.
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Span> {
|
|
||||||
match ty.kind() {
|
|
||||||
ty::Bool
|
|
||||||
| ty::Char
|
|
||||||
| ty::Int(_)
|
|
||||||
| ty::Uint(_)
|
|
||||||
| ty::Float(_)
|
|
||||||
| ty::Error(_)
|
|
||||||
| ty::Str
|
|
||||||
| ty::Never
|
|
||||||
| ty::RawPtr(_, _)
|
|
||||||
| ty::Ref(_, _, _)
|
|
||||||
| ty::FnPtr(_, _)
|
|
||||||
| ty::Tuple(_)
|
|
||||||
| ty::Dynamic(_, _, _)
|
|
||||||
| ty::Alias(_, _)
|
|
||||||
| ty::Bound(_, _)
|
|
||||||
| ty::Pat(_, _)
|
|
||||||
| ty::Placeholder(_)
|
|
||||||
| ty::Infer(_)
|
|
||||||
| ty::Slice(_)
|
|
||||||
| ty::Array(_, _)
|
|
||||||
| ty::UnsafeBinder(_) => None,
|
|
||||||
|
|
||||||
ty::Adt(adt_def, _) => {
|
|
||||||
let did = adt_def.did();
|
|
||||||
let try_local_did_span = |did: DefId| {
|
|
||||||
if let Some(local) = did.as_local() {
|
|
||||||
tcx.source_span(local)
|
|
||||||
} else {
|
|
||||||
tcx.def_span(did)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let dtor = if let Some(dtor) = tcx.adt_destructor(did) {
|
|
||||||
dtor.did
|
|
||||||
} else if let Some(dtor) = tcx.adt_async_destructor(did) {
|
|
||||||
dtor.future
|
|
||||||
} else {
|
|
||||||
return Some(try_local_did_span(did));
|
|
||||||
};
|
|
||||||
let def_key = tcx.def_key(dtor);
|
|
||||||
let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) };
|
|
||||||
let parent_did = DefId { index: parent_index, krate: dtor.krate };
|
|
||||||
Some(try_local_did_span(parent_did))
|
|
||||||
}
|
|
||||||
ty::Coroutine(did, _)
|
|
||||||
| ty::CoroutineWitness(did, _)
|
|
||||||
| ty::CoroutineClosure(did, _)
|
|
||||||
| ty::Closure(did, _)
|
|
||||||
| ty::FnDef(did, _)
|
|
||||||
| ty::Foreign(did) => Some(tcx.def_span(did)),
|
|
||||||
ty::Param(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a moved place at `idx` is a part of a BID.
|
/// Check if a moved place at `idx` is a part of a BID.
|
||||||
/// The use of this check is that we will consider drops on these
|
/// The use of this check is that we will consider drops on these
|
||||||
/// as a drop of the overall BID and, thus, we can exclude it from the diagnosis.
|
/// as a drop of the overall BID and, thus, we can exclude it from the diagnosis.
|
||||||
|
|
|
@ -242,6 +242,15 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:127:5
|
--> $DIR/drop-order-comparisons.rs:127:5
|
||||||
|
|
|
|
||||||
|
@ -267,6 +276,15 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:145:44
|
--> $DIR/drop-order-comparisons.rs:145:44
|
||||||
|
|
|
|
||||||
|
@ -291,6 +309,15 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:247:43
|
--> $DIR/drop-order-comparisons.rs:247:43
|
||||||
|
|
|
|
||||||
|
@ -315,6 +342,15 @@ LL | if let true = e.err(9).is_ok() {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:352:41
|
--> $DIR/drop-order-comparisons.rs:352:41
|
||||||
|
|
|
|
||||||
|
@ -339,6 +375,15 @@ LL | if let Ok(_v) = e.err(8) {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:355:35
|
--> $DIR/drop-order-comparisons.rs:355:35
|
||||||
|
|
|
|
||||||
|
@ -363,6 +408,15 @@ LL | if let Ok(_) = e.err(7) {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:358:34
|
--> $DIR/drop-order-comparisons.rs:358:34
|
||||||
|
|
|
|
||||||
|
@ -387,6 +441,15 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:361:43
|
--> $DIR/drop-order-comparisons.rs:361:43
|
||||||
|
|
|
|
||||||
|
@ -411,6 +474,15 @@ LL | if let Ok(_v) = e.err(5) {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:365:35
|
--> $DIR/drop-order-comparisons.rs:365:35
|
||||||
|
|
|
|
||||||
|
@ -435,6 +507,15 @@ LL | if let Ok(_) = e.err(4) {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:368:34
|
--> $DIR/drop-order-comparisons.rs:368:34
|
||||||
|
|
|
|
||||||
|
@ -459,6 +540,15 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/drop-order-comparisons.rs:571:1
|
||||||
|
|
|
||||||
|
LL | / impl<'b> Drop for LogDrop<'b> {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | self.0.mark(self.1);
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/drop-order-comparisons.rs:404:43
|
--> $DIR/drop-order-comparisons.rs:404:43
|
||||||
|
|
|
|
||||||
|
|
|
@ -8,6 +8,15 @@ LL | if let Some(_value) = Droppy.get() {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope-gated.rs:14:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope-gated.rs:30:5
|
--> $DIR/lint-if-let-rescope-gated.rs:30:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ LL | | };
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope-with-macro.rs:22:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope-with-macro.rs:12:38
|
--> $DIR/lint-if-let-rescope-with-macro.rs:12:38
|
||||||
|
|
|
|
||||||
|
|
|
@ -8,6 +8,15 @@ LL | if let Some(_value) = droppy().get() {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:32:5
|
--> $DIR/lint-if-let-rescope.rs:32:5
|
||||||
|
|
|
|
||||||
|
@ -43,6 +52,24 @@ LL | } else if let Some(_value) = droppy().get() {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:42:5
|
--> $DIR/lint-if-let-rescope.rs:42:5
|
||||||
|
|
|
|
||||||
|
@ -75,6 +102,15 @@ LL | } else if let Some(_value) = droppy().get() {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:54:5
|
--> $DIR/lint-if-let-rescope.rs:54:5
|
||||||
|
|
|
|
||||||
|
@ -101,6 +137,15 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:58:69
|
--> $DIR/lint-if-let-rescope.rs:58:69
|
||||||
|
|
|
|
||||||
|
@ -122,6 +167,15 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:72:53
|
--> $DIR/lint-if-let-rescope.rs:72:53
|
||||||
|
|
|
|
||||||
|
@ -143,6 +197,15 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:78:62
|
--> $DIR/lint-if-let-rescope.rs:78:62
|
||||||
|
|
|
|
||||||
|
@ -164,6 +227,15 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
|
||||||
|
|
|
|
||||||
= warning: this changes meaning in Rust 2024
|
= warning: this changes meaning in Rust 2024
|
||||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
note: value invokes this custom destructor
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:11:1
|
||||||
|
|
|
||||||
|
LL | / impl Drop for Droppy {
|
||||||
|
LL | | fn drop(&mut self) {
|
||||||
|
LL | | println!("dropped");
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
help: the value is now dropped here in Edition 2024
|
help: the value is now dropped here in Edition 2024
|
||||||
--> $DIR/lint-if-let-rescope.rs:90:57
|
--> $DIR/lint-if-let-rescope.rs:90:57
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue