mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
Fix bad caching of ~const Drop
bounds
This commit is contained in:
parent
99b0799608
commit
aaaad5b46b
@ -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
|
||||
}
|
||||
|
@ -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(¶m_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");
|
||||
|
29
src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
Normal file
29
src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
Normal file
@ -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));
|
||||
}
|
Loading…
Reference in New Issue
Block a user