From b7e443397471062e5681ecefb6638577cefb9571 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Jan 2022 20:07:04 -0800 Subject: [PATCH] Foreign types are trivially drop - Also rename a trivial_const_drop to match style of other functions in the util module. - Also add a test for `const Drop` that doesn't depend on a `~const` bound. - Also comment a bit why we remove the const bound during dropck impl check. --- .../src/transform/check_consts/qualifs.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 10 +++++----- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 3 ++- compiler/rustc_typeck/src/check/dropck.rs | 18 +++++++++--------- .../ui/rfc-2632-const-trait-impl/const-drop.rs | 13 +++++++++++++ 6 files changed, 31 insertions(+), 17 deletions(-) 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 8dfdbf5d9dda2..91610b15eb999 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -148,7 +148,7 @@ impl Qualif for NeedsNonConstDrop { 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) { + if ty::util::is_trivially_const_drop(ty) { return false; } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d73fcc28c13b0..96c27d649e4d1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1041,7 +1041,7 @@ pub fn needs_drop_components<'tcx>( } } -pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { +pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { match *ty.kind() { ty::Bool | ty::Char @@ -1055,7 +1055,8 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(_) - | ty::Never => true, + | ty::Never + | ty::Foreign(_) => true, ty::Opaque(..) | ty::Dynamic(..) @@ -1063,7 +1064,6 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { | ty::Bound(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Foreign(_) | ty::Projection(_) | ty::Infer(_) => false, @@ -1071,9 +1071,9 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { // 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::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), - ty::Tuple(tys) => tys.iter().all(|ty| trivial_const_drop(ty.expect_ty())), + ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty.expect_ty())), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 77db3bd2692cc..0099fba920042 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -932,7 +932,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Bound(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Foreign(_) | ty::Projection(_) => { // We don't know if these are `~const Drop`, at least // not structurally... so don't push a candidate. @@ -951,6 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnDef(..) | ty::FnPtr(_) | ty::Never + | ty::Foreign(_) | ty::Array(..) | ty::Slice(_) | ty::Closure(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4c74627f3c67d..3b6a4afafcfd1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1133,7 +1133,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(_) - | ty::Never => {} + | ty::Never + | ty::Foreign(_) => {} // These types are built-in, so we can fast-track by registering // nested predicates for their constituient type(s) diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 46610a0e08db6..89866c20b61d6 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -228,15 +228,15 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let predicate = predicate.kind(); let p = p.kind(); match (predicate.skip_binder(), p.skip_binder()) { - (ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => relator - .relate( - predicate.rebind(ty::TraitPredicate { - constness: ty::BoundConstness::NotConst, - ..a - }), - p.rebind(b), - ) - .is_ok(), + (ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => { + // Since struct predicates cannot have ~const, project the impl predicate + // onto one that ignores the constness. This is equivalent to saying that + // we match a `Trait` bound on the struct with a `Trait` or `~const Trait` + // in the impl. + let non_const_a = + ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a }; + relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok() + } (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => { relator.relate(predicate.rebind(a), p.rebind(b)).is_ok() } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs index 7d610e5277d11..13363c506d54e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -53,6 +53,10 @@ mod t { impl const SomeTrait for () { fn foo() {} } + // non-const impl + impl SomeTrait for i32 { + fn foo() {} + } pub struct ConstDropWithBound(pub core::marker::PhantomData); @@ -61,6 +65,14 @@ mod t { T::foo(); } } + + pub struct ConstDropWithNonconstBound(pub core::marker::PhantomData); + + impl const Drop for ConstDropWithNonconstBound { + fn drop(&mut self) { + // Note: we DON'T use the `T: SomeTrait` bound + } + } } use t::*; @@ -78,6 +90,7 @@ implements_const_drop! { &1, &1 as *const i32, ConstDropWithBound::<()>, + ConstDropWithNonconstBound::, Result::::Ok(1), }