diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1269f2207d5..8dfdbf5d9dd 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -146,15 +146,10 @@ fn in_qualifs(qualifs: &ConstQualifs) -> bool { qualifs.needs_non_const_drop } - fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { - // Avoid selecting for simple cases. - match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() { - Ok([]) => return false, - Err(ty::util::AlwaysRequiresDrop) => return true, - // If we've got a single component, select with that - // to increase the chance that we hit the selection cache. - Ok([t]) => ty = t, - Ok([..]) => {} + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + // Avoid selecting for simple cases, such as builtin types. + if ty::util::trivial_const_drop(ty) { + return false; } let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else { @@ -187,11 +182,15 @@ fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { impl_src, ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) ) { - // If our const drop candidate is not ConstDrop or implied by param, + // If our const drop candidate is not ConstDrop or implied by the param env, // then it's bad return true; } + if impl_src.borrow_nested_obligations().is_empty() { + return false; + } + // If we successfully found one, then select all of the predicates // implied by our const drop impl. let mut fcx = FulfillmentContext::new(); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8793264a47f..71e9197e4f5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1041,6 +1041,42 @@ pub fn needs_drop_components<'tcx>( } } +pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { + match *ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::Str + | ty::RawPtr(_) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(_) => true, + + ty::Opaque(..) + | ty::Dynamic(..) + | ty::Error(_) + | ty::Bound(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Never + | ty::Foreign(_) + | ty::Projection(_) + | ty::Infer(_) => false, + + // Not trivial because they have components, and instead of looking inside, + // we'll just perform trait selection. + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false, + + ty::Array(ty, _) | ty::Slice(ty) => trivial_const_drop(ty), + + ty::Tuple(tys) => tys.iter().all(|ty| trivial_const_drop(ty.expect_ty())), + } +} + // Does the equivalent of // ``` // let v = self.iter().map(|p| p.fold_with(folder)).collect::>();