about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-12-21 12:49:10 +0000
committerbors <bors@rust-lang.org>2021-12-21 12:49:10 +0000
commit8ad3c1dd1d47f9ce7dfdf4a14c70c67e1790b0f5 (patch)
tree0a6fcdb67f780315e0b94d97ec5ec48d6ac1953a
parent3d57c61a9e04dcd3df633f41142009d6dcad4399 (diff)
parentaaaad5b46bd90047fce43672d7848c6c75ceea35 (diff)
downloadrust-8ad3c1dd1d47f9ce7dfdf4a14c70c67e1790b0f5.tar.gz
rust-8ad3c1dd1d47f9ce7dfdf4a14c70c67e1790b0f5.zip
Auto merge of #92149 - fee1-dead:cache-fix, r=oli-obk
Fix bad caching of `~const Drop` bounds

Fixes #92111.
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs29
3 files changed, 41 insertions, 3 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f5a4a4ae24c..37d99766da9 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -734,6 +734,15 @@ pub struct TraitPredicate<'tcx> {
 pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
 
 impl<'tcx> TraitPredicate<'tcx> {
+    pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) {
+        if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) {
+            // remap without changing constness of this predicate.
+            // this is because `T: ~const Drop` has a different meaning to `T: Drop`
+            param_env.remap_constness_with(self.constness)
+        } else {
+            *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
+        }
+    }
     pub fn def_id(self) -> DefId {
         self.trait_ref.def_id
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 85016a701f3..fa88c8ee370 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -730,7 +730,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let mut param_env = obligation.param_env;
 
         fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| {
-            param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
+            pred.remap_constness(self.tcx(), &mut param_env);
             pred
         });
 
@@ -1269,7 +1269,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
         let tcx = self.tcx();
         let mut pred = cache_fresh_trait_pred.skip_binder();
-        param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
+        pred.remap_constness(tcx, &mut param_env);
 
         if self.can_use_global_caches(param_env) {
             if let Some(res) = tcx.selection_cache.get(&param_env.and(pred), tcx) {
@@ -1322,7 +1322,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let tcx = self.tcx();
         let mut pred = cache_fresh_trait_pred.skip_binder();
 
-        param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
+        pred.remap_constness(tcx, &mut param_env);
 
         if !self.can_cache_candidate(&candidate) {
             debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
new file mode 100644
index 00000000000..d30f4edd4b2
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
@@ -0,0 +1,29 @@
+// Regression test for #92111.
+//
+// The issue was that we normalize trait bounds before caching
+// results of selection. Checking that `impl NoDrop for S` requires
+// checking `S: !Drop` because it cannot overlap with the blanket
+// impl. Then we save the (unsatisfied) result from checking `S: Drop`.
+// Then the call to `a` checks whether `S: ~const Drop` but we normalize
+// it to `S: Drop` which the cache claims to be unsatisfied.
+//
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+pub trait Tr {}
+
+#[allow(drop_bounds)]
+impl<T: Drop> Tr for T {}
+
+#[derive(Debug)]
+pub struct S(i32);
+
+impl Tr for S {}
+
+const fn a<T: ~const Drop>(t: T) {}
+
+fn main() {
+    a(S(0));
+}