about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-01-19 20:07:04 -0800
committerMichael Goulet <michael@errs.io>2022-01-19 20:07:04 -0800
commitb7e443397471062e5681ecefb6638577cefb9571 (patch)
tree3f04c86244e49b76c558c75a4d58873b18c0021c
parent8547f5732c003080f940a23eaf3e2e9c052934ae (diff)
downloadrust-b7e443397471062e5681ecefb6638577cefb9571.tar.gz
rust-b7e443397471062e5681ecefb6638577cefb9571.zip
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.
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs3
-rw-r--r--compiler/rustc_typeck/src/check/dropck.rs18
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs13
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 8dfdbf5d9dd..91610b15eb9 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 d73fcc28c13..96c27d649e4 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 77db3bd2692..0099fba9200 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 4c74627f3c6..3b6a4afafcf 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 46610a0e08d..89866c20b61 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 7d610e5277d..13363c506d5 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<T: SomeTrait>(pub core::marker::PhantomData<T>);
 
@@ -61,6 +65,14 @@ mod t {
             T::foo();
         }
     }
+
+    pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+
+    impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> {
+        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::<i32>,
     Result::<i32, !>::Ok(1),
 }