Skip to content

Commit

Permalink
Auto merge of #92149 - fee1-dead:cache-fix, r=oli-obk
Browse files Browse the repository at this point in the history
Fix bad caching of `~const Drop` bounds

Fixes #92111.
  • Loading branch information
bors committed Dec 21, 2021
2 parents 3d57c61 + aaaad5b commit 8ad3c1d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
9 changes: 9 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
});

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down
29 changes: 29 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
Original file line number Diff line number Diff line change
@@ -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));
}

0 comments on commit 8ad3c1d

Please sign in to comment.