diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 283fa56d11f4f..8b9e00fe3f127 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 @@ -1575,7 +1580,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // rule seems to be pretty clearly safe and also still retains // a very high hit rate (~95% when compiling rustc). if !param_env.caller_bounds.is_empty() { - return false; + //return false; } // Avoid using the master cache during coherence and just rely @@ -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/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 276fc8c1dec0f..1a7f358610e59 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -53,7 +53,7 @@ pub fn trait_obligations<'a, 'tcx>( item: Option<&'tcx hir::Item>, ) -> Vec> { let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item }; - wf.compute_trait_ref(trait_ref, Elaborate::All); + wf.compute_trait_ref(trait_ref, Elaborate::All, false); wf.normalize() } @@ -69,7 +69,7 @@ pub fn predicate_obligations<'a, 'tcx>( // (*) ok to skip binders, because wf code is prepared for it match *predicate { ty::Predicate::Trait(ref t) => { - wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*) + wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None, false); // (*) } ty::Predicate::RegionOutlives(..) => { } @@ -163,14 +163,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. - fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { + fn compute_trait_ref( + &mut self, + trait_ref: &ty::TraitRef<'tcx>, + elaborate: Elaborate, + is_proj: bool, + ) { let tcx = self.infcx.tcx; - let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; - let item = &self.item; + let item = self.item; let extend_cause_with_original_assoc_item_obligation = | cause: &mut traits::ObligationCause<'_>, pred: &ty::Predicate<'_>, @@ -313,26 +317,30 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } }; - if let Elaborate::All = elaborate { - let trait_assoc_items = tcx.associated_items(trait_ref.def_id); - - let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); - let implied_obligations = traits::elaborate_predicates(tcx, predicates); - let implied_obligations = implied_obligations.map(|pred| { - let mut cause = cause.clone(); - extend_cause_with_original_assoc_item_obligation( - &mut cause, - &pred, - trait_assoc_items.clone(), - ); - traits::Obligation::new(cause, param_env, pred) - }); - self.out.extend(implied_obligations); - } + if !is_proj { + let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); + + if let Elaborate::All = elaborate { + let trait_assoc_items = tcx.associated_items(trait_ref.def_id); + + let predicates = obligations.iter() + .map(|obligation| obligation.predicate.clone()) + .collect(); + let implied_obligations = traits::elaborate_predicates(tcx, predicates); + let implied_obligations = implied_obligations.map(|pred| { + let mut cause = cause.clone(); + extend_cause_with_original_assoc_item_obligation( + &mut cause, + &pred, + trait_assoc_items.clone(), + ); + traits::Obligation::new(cause, param_env, pred) + }); + self.out.extend(implied_obligations); + } - self.out.extend(obligations); + self.out.extend(obligations); + } self.out.extend(trait_ref.substs.types() .filter(|ty| !ty.has_escaping_bound_vars()) @@ -350,7 +358,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // WF and (b) the trait-ref holds. (It may also be // normalizable and be WF that way.) let trait_ref = data.trait_ref(self.infcx.tcx); - self.compute_trait_ref(&trait_ref, Elaborate::None); + self.compute_trait_ref(&trait_ref, Elaborate::None, true); if !data.has_escaping_bound_vars() { let predicate = trait_ref.to_predicate(); diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index 5ef1b23cbcd21..8f3fe41a7a174 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -6,13 +6,6 @@ LL | trait Foo: Iterator {} LL | trait Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0282]: type annotations needed - --> $DIR/associated-types-overridden-binding.rs:7:1 - | -LL | trait U32Iterator = I32Iterator; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 13c9c09461eae..724727d0c35f9 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,65 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6 - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ - -error[E0308]: mismatched types - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the lifetime `'a` as defined on the impl at 26:6... - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5 - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ - error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/issue-20831-debruijn.rs:28:5 | @@ -92,7 +30,6 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> { expected Publisher<'_> found Publisher<'_> -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0495. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`.