about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs174
1 files changed, 6 insertions, 168 deletions
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 e3260e45bc5..7d77fffa83f 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<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.
 /// 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.