From 1d1298ea5f83b1e6714f25b0b63a78c37712b240 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 21:12:19 +0200 Subject: [PATCH] rustc: include ParamEnv in global trait select/eval cache keys. --- src/librustc/traits/project.rs | 10 +++----- src/librustc/traits/select.rs | 25 +++++++++++-------- .../type-alias-impl-trait/bound_reduction2.rs | 1 + .../bound_reduction2.stderr | 14 +++++++++-- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index c345b9a969c90..1fdec5f015251 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1079,12 +1079,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if !is_default { true } else if obligation.param_env.reveal == Reveal::All { - debug_assert!(!poly_trait_ref.needs_infer()); - if !poly_trait_ref.needs_subst() { - true - } else { - false - } + // NOTE(eddyb) inference variables can resolve to parameters, so + // assume `poly_trait_ref` isn't monomorphic, if it contains any. + let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); + !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() } else { false } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 5f324527a2725..4e172f50b8f2d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -204,7 +204,10 @@ struct TraitObligationStack<'prev, 'tcx> { #[derive(Clone, Default)] pub struct SelectionCache<'tcx> { hashmap: Lock< - FxHashMap, WithDepNode>>>, + FxHashMap< + ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>, + WithDepNode>>, + >, >, } @@ -490,7 +493,9 @@ impl<'tcx> From for SelectionError<'tcx> { #[derive(Clone, Default)] pub struct EvaluationCache<'tcx> { - hashmap: Lock, WithDepNode>>, + hashmap: Lock< + FxHashMap>, WithDepNode>, + >, } impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { @@ -1143,7 +1148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { let cache = tcx.evaluation_cache.hashmap.borrow(); - if let Some(cached) = cache.get(&trait_ref) { + if let Some(cached) = cache.get(¶m_env.and(trait_ref)) { return Some(cached.get(tcx)); } } @@ -1151,7 +1156,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .evaluation_cache .hashmap .borrow() - .get(&trait_ref) + .get(¶m_env.and(trait_ref)) .map(|v| v.get(tcx)) } @@ -1182,7 +1187,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .evaluation_cache .hashmap .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, result)); + .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result)); return; } } @@ -1195,7 +1200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .evaluation_cache .hashmap .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, result)); + .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result)); } /// For various reasons, it's possible for a subobligation @@ -1602,7 +1607,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { let cache = tcx.selection_cache.hashmap.borrow(); - if let Some(cached) = cache.get(&trait_ref) { + if let Some(cached) = cache.get(¶m_env.and(*trait_ref)) { return Some(cached.get(tcx)); } } @@ -1610,7 +1615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .selection_cache .hashmap .borrow() - .get(trait_ref) + .get(¶m_env.and(*trait_ref)) .map(|v| v.get(tcx)) } @@ -1671,7 +1676,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx.selection_cache .hashmap .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, candidate)); + .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate)); return; } } @@ -1685,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .selection_cache .hashmap .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, candidate)); + .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate)); } fn assemble_candidates<'o>( diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index 919446877a142..1becb1e83a5ac 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -9,6 +9,7 @@ trait TraitWithAssoc { type Foo = impl Trait; //~^ ERROR could not find defining uses +//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied trait Trait {} diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index bb22d582f2167..1eb4cf2a80255 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,5 +1,14 @@ +error[E0277]: the trait bound `T: TraitWithAssoc` is not satisfied + --> $DIR/bound_reduction2.rs:10:1 + | +LL | type Foo = impl Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T` +... +LL | fn foo_desugared(_: T) -> Foo { + | -- help: consider further restricting this bound: `T: TraitWithAssoc +` + error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `::Assoc` - --> $DIR/bound_reduction2.rs:17:1 + --> $DIR/bound_reduction2.rs:18:1 | LL | / fn foo_desugared(_: T) -> Foo { LL | | () @@ -12,5 +21,6 @@ error: could not find defining uses LL | type Foo = impl Trait; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0277`.