diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index 1a601d723cb7bfe74645b4e3fcb812161c1128de..5020dc4132cc34a3d017767339feaf2e66f7cefa 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -223,7 +223,7 @@ fn declared_generic_bounds_from_env_with_compare_fn( // like `T` and `T::Item`. It may not work as well for things // like `>::Item`. let c_b = self.param_env.caller_bounds; - let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b); + let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -315,15 +315,12 @@ fn region_bounds_declared_on_associated_item( let tcx = self.tcx; let assoc_item = tcx.associated_item(assoc_item_def_id); let trait_def_id = assoc_item.container.assert_trait(); - let trait_predicates = - tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p).collect(); + let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p); let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); self.collect_outlives_from_predicate_list( move |ty| ty == identity_proj, - traits::elaborate_predicates(tcx, trait_predicates) - .map(|o| o.predicate) - .collect::>(), + traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate), ) .map(|b| b.1) } @@ -337,10 +334,9 @@ fn region_bounds_declared_on_associated_item( fn collect_outlives_from_predicate_list( &self, compare_ty: impl Fn(Ty<'tcx>) -> bool, - predicates: impl IntoIterator>>, + predicates: impl Iterator>>, ) -> impl Iterator, ty::Region<'tcx>>> { predicates - .into_iter() .filter_map(|p| p.as_ref().to_opt_type_outlives()) .filter_map(|p| p.no_bound_vars()) .filter(move |p| compare_ty(p.0)) diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 3f63d25fb4723ad92109f62fb965a6843e75a20c..55bea57f3e24330d1af5f106954d38bee589d6ab 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -97,24 +97,22 @@ pub fn elaborate_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Elaborator<'tcx> { - elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()]) + elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate())) } pub fn elaborate_trait_refs<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator>, ) -> Elaborator<'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect(); + let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()); elaborate_predicates(tcx, predicates) } pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, - mut predicates: Vec>, + predicates: impl Iterator>, ) -> Elaborator<'tcx> { - let mut visited = PredicateSet::new(tcx); - predicates.retain(|pred| visited.insert(pred)); - let obligations: Vec<_> = + let obligations = predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect(); elaborate_obligations(tcx, obligations) } @@ -151,21 +149,20 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|(pred, span)| { + let obligations = predicates.predicates.into_iter().map(|(pred, span)| { predicate_obligation( pred.subst_supertrait(tcx, &data.to_poly_trait_ref()), Some(*span), ) }); - debug!("super_predicates: data={:?} predicates={:?}", data, &obligations); + debug!("super_predicates: data={:?}", data); // Only keep those bounds that we haven't already seen. // This is necessary to prevent infinite recursion in some // cases. One common case is when people define // `trait Sized: Sized { }` rather than `trait Sized { }`. let visited = &mut self.visited; - let obligations = - obligations.filter(|obligation| visited.insert(&obligation.predicate)); + let obligations = obligations.filter(|o| visited.insert(&o.predicate)); self.stack.extend(obligations); } diff --git a/src/librustc_middle/ty/trait_def.rs b/src/librustc_middle/ty/trait_def.rs index 2686759ab971b965fccd41507c1752320fdf37f4..72dfebd8ccd44e79c8e4eca565324162e73031c6 100644 --- a/src/librustc_middle/ty/trait_def.rs +++ b/src/librustc_middle/ty/trait_def.rs @@ -168,15 +168,13 @@ pub fn for_each_relevant_impl( } /// Returns a vector containing all impls - pub fn all_impls(self, def_id: DefId) -> Vec { - let impls = self.trait_impls_of(def_id); + pub fn all_impls(self, def_id: DefId) -> impl Iterator + 'tcx { + let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id); - impls - .blanket_impls - .iter() - .chain(impls.non_blanket_impls.values().flatten()) + blanket_impls + .into_iter() + .chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten()) .cloned() - .collect() } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index bad0b94f3ece71b03eead3f0a98c188418356fa4..abe9249ec3766136a92d69110fcbed1d19c70eca 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -116,8 +116,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<' .predicates_of(source.def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) - .collect(); + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); if !traits::normalize_and_test_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 8ff8f5734c9b06524e4a0d1a80bf0c6391e7267f..e208698e962f9d30eb0b230e47d73f74ad592dab 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -418,7 +418,7 @@ fn constrain_opaque_type>( let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); let required_region_bounds = - required_region_bounds(tcx, opaque_type, bounds.predicates); + required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter()); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -1137,7 +1137,8 @@ fn fold_opaque_ty( debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone()); + let required_region_bounds = + required_region_bounds(tcx, ty, bounds.predicates.iter().cloned()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1259,17 +1260,15 @@ pub fn may_define_opaque_type( crate fn required_region_bounds( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, - predicates: Vec>, + predicates: impl Iterator>, ) -> Vec> { - debug!( - "required_region_bounds(erased_self_ty={:?}, predicates={:?})", - erased_self_ty, predicates - ); + debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty); assert!(!erased_self_ty.has_escaping_bound_vars()); traits::elaborate_predicates(tcx, predicates) .filter_map(|obligation| { + debug!("required_region_bounds(obligation={:?})", obligation); match obligation.predicate { ty::Predicate::Projection(..) | ty::Predicate::Trait(..) diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs index 052de4a4e5b555682ea13162fb964a15449cf12c..6326a87c5edc366014692dc5aeb4ab8f3254347f 100644 --- a/src/librustc_trait_selection/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -281,7 +281,7 @@ fn evaluate_predicates( }, })); - let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect(); + let computed_preds = param_env.caller_bounds.iter().cloned(); let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds.iter().cloned().collect(); @@ -358,10 +358,11 @@ fn evaluate_predicates( _ => panic!("Unexpected error for '{:?}': {:?}", ty, result), }; - computed_preds.extend(user_computed_preds.iter().cloned()); - let normalized_preds = - elaborate_predicates(tcx, computed_preds.iter().cloned().collect()) - .map(|o| o.predicate); + let normalized_preds = elaborate_predicates( + tcx, + computed_preds.clone().chain(user_computed_preds.iter().cloned()), + ) + .map(|o| o.predicate); new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None); } @@ -739,7 +740,7 @@ fn evaluate_nested_obligations( if p.ty().skip_binder().has_infer_types() { if !self.evaluate_nested_obligations( ty, - v.clone().iter().cloned(), + v.into_iter(), computed_preds, fresh_preds, predicates, diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 35eb5d73adac6cb25a9cbebf0835842fb7000d2e..fa2af24c9453464b1aec30a9dbee0c3eba8a2a0f 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1017,7 +1017,7 @@ fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) } }; - for obligation in super::elaborate_predicates(self.tcx, vec![*cond]) { + for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) { if let ty::Predicate::Trait(implication, _) = obligation.predicate { let error = error.to_poly_trait_ref(); let implication = implication.to_poly_trait_ref(); @@ -1218,8 +1218,7 @@ fn find_similar_impl_candidates( match simp { Some(simp) => all_impls - .iter() - .filter_map(|&def_id| { + .filter_map(|def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); if let Some(imp_simp) = imp_simp { @@ -1227,13 +1226,10 @@ fn find_similar_impl_candidates( return None; } } - Some(imp) }) .collect(), - None => { - all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() - } + None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(), } } diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index f8fc155f582b82e6d7c0611f8bf50aef4f3eb6f2..c5dbe816295504c7d391b03b0c27ebe35d4fce50 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -110,8 +110,8 @@ pub enum TraitQueryMode { pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> PredicateObligations<'tcx> { + generic_bounds: ty::InstantiatedPredicates<'tcx>, +) -> impl Iterator> { util::predicates_for_generics(cause, 0, param_env, generic_bounds) } @@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>( ); let mut predicates: Vec<_> = - util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) + util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.into_iter().cloned()) .map(|obligation| obligation.predicate) .collect(); diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index d9fba1fd78392e69e11f41c2fc799729dd788311..96b2b904e65436fe26709ffc06e8c388da38b5ef 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -302,7 +302,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Search for a predicate like `Self : Sized` amongst the trait bounds. let predicates = tcx.predicates_of(def_id); let predicates = predicates.instantiate_identity(tcx).predicates; - elaborate_predicates(tcx, predicates).any(|obligation| match obligation.predicate { + elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| match obligation.predicate { ty::Predicate::Trait(ref trait_pred, _) => { trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0) } diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 4d02c5eb2301d3a44a9bc3391f2eca7f30cdbf3e..2b4a0409fd1e23a2e90f95d3e34f6ad318259e8e 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -900,7 +900,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // If so, extract what we know from the trait and try to come up with a good answer. let trait_predicates = tcx.predicates_of(def_id); let bounds = trait_predicates.instantiate(tcx, substs); - let bounds = elaborate_predicates(tcx, bounds.predicates).map(|o| o.predicate); + let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate); assemble_candidates_from_predicates( selcx, obligation, @@ -911,16 +911,14 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( ) } -fn assemble_candidates_from_predicates<'cx, 'tcx, I>( +fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, obligation_trait_ref: &ty::TraitRef<'tcx>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, - env_predicates: I, -) where - I: IntoIterator>, -{ + env_predicates: impl Iterator>, +) { debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); let infcx = selcx.infcx(); for predicate in env_predicates { @@ -1153,10 +1151,8 @@ fn confirm_object_candidate<'cx, 'tcx>( object_ty ), }; - let env_predicates = data - .projection_bounds() - .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()) - .collect(); + let env_predicates = + data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()); let env_predicate = { let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index 45fda3004b09b42b77a79c1644cb394888d3568a..dfbb07424487d43a786ec1c62a117a8fb71cb62f 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -1443,7 +1443,8 @@ fn match_projection_obligation_against_definition_bounds( bounds ); - let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates); + let elaborated_predicates = + util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter()); let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| { self.infcx.probe(|_| { self.match_projection( diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index beebddd72a82033f1314dddd4be727013e0f812b..897ac0d736e08fb1858b92d6339171f7f042a590 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -189,26 +189,22 @@ fn fulfill_implication<'a, 'tcx>( let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); - let (target_trait_ref, mut obligations) = + let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs); - debug!( - "fulfill_implication: target_trait_ref={:?}, obligations={:?}", - target_trait_ref, obligations - ); // do the impls unify? If not, no specialization. - match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) { - Ok(InferOk { obligations: o, .. }) => { - obligations.extend(o); - } - Err(_) => { - debug!( - "fulfill_implication: {:?} does not unify with {:?}", - source_trait_ref, target_trait_ref - ); - return Err(()); - } - } + let more_obligations = + match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) + { + Ok(InferOk { obligations, .. }) => obligations, + Err(_) => { + debug!( + "fulfill_implication: {:?} does not unify with {:?}", + source_trait_ref, target_trait_ref + ); + return Err(()); + } + }; // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) @@ -226,7 +222,7 @@ fn fulfill_implication<'a, 'tcx>( // we already make a mockery out of the region system, so // why not ignore them a bit earlier? let mut fulfill_cx = FulfillmentContext::new_ignoring_regions(); - for oblig in obligations.into_iter() { + for oblig in obligations.chain(more_obligations) { fulfill_cx.register_predicate_obligation(&infcx, oblig); } match fulfill_cx.select_all_or_error(infcx) { @@ -261,7 +257,7 @@ pub(super) fn specialization_graph_provider( ) -> &specialization_graph::Graph { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls = tcx.all_impls(trait_id); + let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect(); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs index ffece42ec306ce3e18d8cb177942b91d3aaa725c..4aceccf64ce65156351dacf01680099a14fe6047 100644 --- a/src/librustc_trait_selection/traits/util.rs +++ b/src/librustc_trait_selection/traits/util.rs @@ -81,12 +81,10 @@ fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self pub fn expand_trait_aliases<'tcx>( tcx: TyCtxt<'tcx>, - trait_refs: impl IntoIterator, Span)>, + trait_refs: impl Iterator, Span)>, ) -> TraitAliasExpander<'tcx> { - let items: Vec<_> = trait_refs - .into_iter() - .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) - .collect(); + let items: Vec<_> = + trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect(); TraitAliasExpander { tcx, stack: items } } @@ -199,7 +197,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, impl_def_id: DefId, impl_substs: SubstsRef<'tcx>, -) -> (ty::TraitRef<'tcx>, Vec>) { +) -> (ty::TraitRef<'tcx>, impl Iterator>) { let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = @@ -210,13 +208,11 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( let Normalized { value: predicates, obligations: normalization_obligations2 } = super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates); let impl_obligations = - predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates); + predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates); - let impl_obligations: Vec<_> = impl_obligations - .into_iter() - .chain(normalization_obligations1) - .chain(normalization_obligations2) - .collect(); + let impl_obligations = impl_obligations + .chain(normalization_obligations1.into_iter()) + .chain(normalization_obligations2.into_iter()); (impl_trait_ref, impl_obligations) } @@ -226,20 +222,16 @@ pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> Vec> { + generic_bounds: ty::InstantiatedPredicates<'tcx>, +) -> impl Iterator> { debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - generic_bounds - .predicates - .iter() - .map(|&predicate| Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate, - }) - .collect() + generic_bounds.predicates.into_iter().map(move |predicate| Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate, + }) } pub fn predicate_for_trait_ref<'tcx>( diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index f6953971ef5bcbbc74e618caa43caedd597f5585..7eabdf706ef9f0941e0689cc9172ef7a7dba007c 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -140,7 +140,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: &ty::Predicate<'_>, - mut trait_assoc_items: impl Iterator, + mut trait_assoc_items: impl Iterator, ) { debug!( "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", @@ -232,35 +232,34 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo let item = self.item; + let extend = |obligation: traits::PredicateObligation<'tcx>| { + let mut cause = cause.clone(); + if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { + let derived_cause = traits::DerivedObligationCause { + parent_trait_ref, + parent_code: Rc::new(obligation.cause.code.clone()), + }; + cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause); + } + extend_cause_with_original_assoc_item_obligation( + tcx, + trait_ref, + item, + &mut cause, + &obligation.predicate, + tcx.associated_items(trait_ref.def_id).in_definition_order(), + ); + traits::Obligation::new(cause, param_env, obligation.predicate) + }; + if let Elaborate::All = elaborate { - let implied_obligations = traits::util::elaborate_obligations(tcx, obligations.clone()); - let implied_obligations = implied_obligations.map(|obligation| { - debug!("compute_trait_ref implied_obligation {:?}", obligation); - debug!("compute_trait_ref implied_obligation cause {:?}", obligation.cause); - let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { - let derived_cause = traits::DerivedObligationCause { - parent_trait_ref, - parent_code: Rc::new(obligation.cause.code.clone()), - }; - cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause); - } - extend_cause_with_original_assoc_item_obligation( - tcx, - trait_ref, - item, - &mut cause, - &obligation.predicate, - tcx.associated_items(trait_ref.def_id).in_definition_order().copied(), - ); - debug!("compute_trait_ref new cause {:?}", cause); - traits::Obligation::new(cause, param_env, obligation.predicate) - }); + let implied_obligations = traits::util::elaborate_obligations(tcx, obligations); + let implied_obligations = implied_obligations.map(extend); self.out.extend(implied_obligations); + } else { + self.out.extend(obligations); } - self.out.extend(obligations); - self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map( |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)), )); @@ -627,16 +626,13 @@ pub fn object_region_bounds<'tcx>( // a placeholder type. let open_ty = tcx.mk_ty_infer(ty::FreshTy(0)); - let predicates = existential_predicates - .iter() - .filter_map(|predicate| { - if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { - None - } else { - Some(predicate.with_self_ty(tcx, open_ty)) - } - }) - .collect(); + let predicates = existential_predicates.iter().filter_map(|predicate| { + if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { + None + } else { + Some(predicate.with_self_ty(tcx, open_ty)) + } + }); required_region_bounds(tcx, open_ty, predicates) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 23c7954d088786e1183cab6d1acc01150520adef..64dc34ab3b0a7d0bec9a238e60b594a5b74ed2fc 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -114,7 +114,7 @@ fn confirm( // a custom error in that case. if illegal_sized_bound.is_none() { let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig)); - self.add_obligations(method_ty, all_substs, &method_predicates); + self.add_obligations(method_ty, all_substs, method_predicates); } // Create the final `MethodCallee`. @@ -394,7 +394,7 @@ fn add_obligations( &mut self, fty: Ty<'tcx>, all_substs: SubstsRef<'tcx>, - method_predicates: &ty::InstantiatedPredicates<'tcx>, + method_predicates: ty::InstantiatedPredicates<'tcx>, ) { debug!( "add_obligations: fty={:?} all_substs={:?} method_predicates={:?}", @@ -571,7 +571,7 @@ fn predicates_require_illegal_sized_bound( None => return None, }; - traits::elaborate_predicates(self.tcx, predicates.predicates.clone()) + traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied()) .filter_map(|obligation| match obligation.predicate { ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { let span = predicates diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 90a9f8a4d6f7705d938d4a86a1efdfaad3d02f58..ae2061a2e3f3c96520bfb4406b5987d3dde39779 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -390,7 +390,7 @@ pub fn lookup_method_in_trait( assert!(!bounds.has_escaping_bound_vars()); let cause = traits::ObligationCause::misc(span, self.body_id); - obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, &bounds)); + obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig)); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3f159fe5e302967faa0416af54cd198e3b4f84db..03e32c21a54ac846b2dd1d4ddf68a29a39898681 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1342,7 +1342,7 @@ fn consider_probe( // clauses) that must be considered. Make sure that those // match as well (or at least may match, sometimes we // don't have enough information to fully evaluate). - let candidate_obligations: Vec<_> = match probe.kind { + match probe.kind { InherentImplCandidate(ref substs, ref ref_obligations) => { // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container.id(); @@ -1353,19 +1353,23 @@ fn consider_probe( // Convert the bounds into obligations. let impl_obligations = - traits::predicates_for_generics(cause, self.param_env, &impl_bounds); + traits::predicates_for_generics(cause, self.param_env, impl_bounds); - debug!("impl_obligations={:?}", impl_obligations); - impl_obligations - .into_iter() + let candidate_obligations = impl_obligations .chain(norm_obligations.into_iter()) - .chain(ref_obligations.iter().cloned()) - .collect() + .chain(ref_obligations.iter().cloned()); + // Evaluate those obligations to see if they might possibly hold. + for o in candidate_obligations { + let o = self.resolve_vars_if_possible(&o); + if !self.predicate_may_hold(&o) { + result = ProbeResult::NoMatch; + possibly_unsatisfied_predicates.push((o.predicate, None)); + } + } } ObjectCandidate | WhereClauseCandidate(..) => { // These have no additional conditions to check. - vec![] } TraitCandidate(trait_ref) => { @@ -1412,17 +1416,11 @@ fn consider_probe( return ProbeResult::NoMatch; } } - vec![] } - }; - - debug!( - "consider_probe - candidate_obligations={:?} sub_obligations={:?}", - candidate_obligations, sub_obligations - ); + } // Evaluate those obligations to see if they might possibly hold. - for o in candidate_obligations.into_iter().chain(sub_obligations) { + for o in sub_obligations { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d631d3c33405ec8f420f68d928b357411fe1c935..fc96a26a2c7eec2be910a97566434409ed952046 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3460,7 +3460,7 @@ pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr<'_>) { pub fn add_obligations_for_parameters( &self, cause: traits::ObligationCause<'tcx>, - predicates: &ty::InstantiatedPredicates<'tcx>, + predicates: ty::InstantiatedPredicates<'tcx>, ) { assert!(!predicates.has_escaping_bound_vars()); @@ -4411,7 +4411,7 @@ pub fn check_struct_path( let (bounds, _) = self.instantiate_bounds(path_span, did, substs); let cause = traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did)); - self.add_obligations_for_parameters(cause, &bounds); + self.add_obligations_for_parameters(cause, bounds); Some((variant, ty)) } else { @@ -5681,9 +5681,8 @@ fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef for (i, mut obligation) in traits::predicates_for_generics( traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), self.param_env, - &bounds, + bounds, ) - .into_iter() .enumerate() { // This makes the error point at the bound, but we want to point at the argument diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ffe1dcbd444039c6702ac13a991c63e2d8ce34f4..7eb8bf7c6be97803a89daffbd07b1263444cffb0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1233,7 +1233,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id(id); - let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p).collect(); + let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p); // Check elaborated bounds. let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index c7ef07bde30cf9c8ad1ea68e0997d56f8856672a..8b12535b3a2cf2c57873f29a9319bca9c35ae26b 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -329,7 +329,7 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl AlwaysApplicable for D { } - let always_applicable_traits: Vec<_> = impl1_predicates + let always_applicable_traits = impl1_predicates .predicates .iter() .filter(|predicate| { @@ -338,8 +338,7 @@ fn check_predicates<'tcx>( Some(TraitSpecializationKind::AlwaysApplicable) ) }) - .copied() - .collect(); + .copied(); // Include the well-formed predicates of the type parameters of the impl. for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() {