From a348d622adf4559286f36617a40ea88ef001b5e6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Feb 2025 03:34:33 +0000 Subject: [PATCH] Print out destructor --- Cargo.lock | 1 + compiler/rustc_lint/Cargo.toml | 1 + compiler/rustc_lint/messages.ftl | 5 + compiler/rustc_lint/src/if_let_rescope.rs | 57 ++++-- compiler/rustc_middle/src/ty/mod.rs | 1 + .../src/ty/significant_drop_order.rs | 172 +++++++++++++++++ .../src/lint_tail_expr_drop_order.rs | 174 +----------------- .../drop/drop-order-comparisons.e2021.stderr | 90 +++++++++ ...nt-if-let-rescope-gated.edition2021.stderr | 9 + .../lint-if-let-rescope-with-macro.stderr | 9 + tests/ui/drop/lint-if-let-rescope.stderr | 72 ++++++++ 11 files changed, 410 insertions(+), 181 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/significant_drop_order.rs diff --git a/Cargo.lock b/Cargo.lock index 4401489813a40..07a84728cd83e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3911,6 +3911,7 @@ dependencies = [ "rustc_target", "rustc_trait_selection", "rustc_type_ir", + "smallvec", "tracing", "unicode-security", ] diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 24e7b40c8a2d3..d6014f5006ad0 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -24,6 +24,7 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } +smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unicode-security = "0.1.0" # tidy-alphabetical-end diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 679367634276d..d51865810b9a8 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -333,6 +333,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> *[other] {" "}{$identifier_type} } 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 .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 diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index c1aa95667da68..6ccf3ba3abc27 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -7,12 +7,16 @@ use rustc_errors::{ Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, }; use rustc_hir::{self as hir, HirIdSet}; -use rustc_macros::LintDiagnostic; -use rustc_middle::ty::TyCtxt; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; +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::{declare_lint, impl_lint_pass}; -use rustc_span::Span; use rustc_span::edition::Edition; +use rustc_span::{DUMMY_SP, Span}; +use smallvec::SmallVec; use crate::{LateContext, LateLintPass}; @@ -129,6 +133,7 @@ impl IfLetRescope { hir::ExprKind::If(_cond, _conseq, Some(alt)) => alt.span.shrink_to_hi(), _ => return, }; + let mut seen_dyn = false; let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr); let mut significant_droppers = vec![]; let mut lifetime_ends = vec![]; @@ -136,6 +141,7 @@ impl IfLetRescope { let mut alt_heads = vec![]; let mut match_heads = vec![]; let mut consequent_heads = vec![]; + let mut destructors = vec![]; let mut first_if_to_lint = None; let mut first_if_to_rewrite = false; let mut empty_alt = false; @@ -159,11 +165,25 @@ impl IfLetRescope { let before_conseq = conseq.span.shrink_to_lo(); 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 }).visit_expr(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))); - significant_droppers.push(significant_dropper); + significant_droppers.push(drop_span); lifetime_ends.push(lifetime_end); if ty_ascription.is_some() || !expr.span.can_be_used_for_suggestions() @@ -226,6 +246,7 @@ impl IfLetRescope { hir_id, span, IfLetRescopeLint { + destructors, significant_droppers, lifetime_ends, rewrite: first_if_to_rewrite.then_some(IfLetRescopeRewrite { @@ -287,6 +308,8 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope { #[derive(LintDiagnostic)] #[diag(lint_if_let_rescope)] struct IfLetRescopeLint { + #[subdiagnostic] + destructors: Vec, #[label] significant_droppers: Vec, #[help] @@ -346,6 +369,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 ConsequentRewrite { @@ -368,16 +399,16 @@ struct FindSignificantDropper<'tcx, 'a> { } impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { - type Result = ControlFlow; + type Result = ControlFlow<(Span, SmallVec<[Ty<'tcx>; 4]>)>; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result { - if self - .cx - .typeck_results() - .expr_ty(expr) - .has_significant_drop(self.cx.tcx, self.cx.typing_env()) - { - return ControlFlow::Break(expr.span); + 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::Break((expr.span, drop_tys)); } match expr.kind { hir::ExprKind::ConstBlock(_) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8ed5a118093f3..aead20748aadf 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -121,6 +121,7 @@ pub mod normalize_erasing_regions; pub mod pattern; pub mod print; pub mod relate; +pub mod significant_drop_order; pub mod trait_def; pub mod util; pub mod visit; diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs new file mode 100644 index 0000000000000..7f0d82d89fede --- /dev/null +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -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`, whose drop is delegated to `K` and `V`. +fn true_significant_drop_ty<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option; 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>, +) -> 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 { + 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, + } +} diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index e3260e45bc524..7d77fffa83fd1 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Subdiagnostic; 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::{IndexSlice, IndexVec}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -15,7 +15,10 @@ use rustc_middle::mir::{ self, BasicBlock, Body, ClearCrossCrate, Local, Location, Place, StatementKind, TerminatorKind, 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::move_paths::{LookupResult, MoveData, MovePathIndex}; 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_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::data_structures::IndexMap; -use smallvec::{SmallVec, smallvec}; -use tracing::{debug, instrument}; +use tracing::debug; fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool { 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`, whose drop is delegated to `K` and `V`. -fn true_significant_drop_ty<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, -) -> Option; 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>, -) -> 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 { - 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. /// 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. diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr index 158d18f68826b..601b0a38412f0 100644 --- a/tests/ui/drop/drop-order-comparisons.e2021.stderr +++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr @@ -242,6 +242,15 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() { | = warning: this changes meaning in Rust 2024 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $DIR/drop-order-comparisons.rs:404:43 | diff --git a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr index 546a5fe0fd045..070ba1c6a4cfa 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr @@ -8,6 +8,15 @@ LL | if let Some(_value) = Droppy.get() { | = warning: this changes meaning in Rust 2024 = note: for more information, see +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 --> $DIR/lint-if-let-rescope-gated.rs:30:5 | diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index 029d5c7492936..f1ca0ba57de4f 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -15,6 +15,15 @@ LL | | }; | = warning: this changes meaning in Rust 2024 = note: for more information, see +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 --> $DIR/lint-if-let-rescope-with-macro.rs:12:38 | diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 2b0fcb7a938a6..1411c33a3194f 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -8,6 +8,15 @@ LL | if let Some(_value) = droppy().get() { | = warning: this changes meaning in Rust 2024 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $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 = note: for more information, see +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 --> $DIR/lint-if-let-rescope.rs:90:57 |