about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_infer/infer/outlives/verify.rs12
-rw-r--r--src/librustc_infer/traits/util.rs17
-rw-r--r--src/librustc_middle/ty/trait_def.rs12
-rw-r--r--src/librustc_mir/transform/const_prop.rs3
-rw-r--r--src/librustc_trait_selection/opaque_types.rs13
-rw-r--r--src/librustc_trait_selection/traits/auto_trait.rs13
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs10
-rw-r--r--src/librustc_trait_selection/traits/mod.rs6
-rw-r--r--src/librustc_trait_selection/traits/object_safety.rs2
-rw-r--r--src/librustc_trait_selection/traits/project.rs16
-rw-r--r--src/librustc_trait_selection/traits/select.rs3
-rw-r--r--src/librustc_trait_selection/traits/specialize/mod.rs34
-rw-r--r--src/librustc_trait_selection/traits/util.rs40
-rw-r--r--src/librustc_trait_selection/traits/wf.rs68
-rw-r--r--src/librustc_typeck/check/method/confirm.rs6
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs30
-rw-r--r--src/librustc_typeck/check/mod.rs7
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/impl_wf_check/min_specialization.rs5
20 files changed, 132 insertions, 169 deletions
diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs
index 1a601d723cb..5020dc4132c 100644
--- a/src/librustc_infer/infer/outlives/verify.rs
+++ b/src/librustc_infer/infer/outlives/verify.rs
@@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         // like `T` and `T::Item`. It may not work as well for things
         // like `<T as Foo<'a>>::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 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         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::<Vec<_>>(),
+            traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
         )
         .map(|b| b.1)
     }
@@ -337,10 +334,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     fn collect_outlives_from_predicate_list(
         &self,
         compare_ty: impl Fn(Ty<'tcx>) -> bool,
-        predicates: impl IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
+        predicates: impl Iterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
     ) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, 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 3f63d25fb47..55bea57f3e2 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<Item = ty::PolyTraitRef<'tcx>>,
 ) -> 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<ty::Predicate<'tcx>>,
+    predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
 ) -> 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 @@ impl Elaborator<'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 2686759ab97..72dfebd8ccd 100644
--- a/src/librustc_middle/ty/trait_def.rs
+++ b/src/librustc_middle/ty/trait_def.rs
@@ -168,15 +168,13 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Returns a vector containing all impls
-    pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
-        let impls = self.trait_impls_of(def_id);
+    pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + '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 bad0b94f3ec..abe9249ec37 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -116,8 +116,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             .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 8ff8f5734c9..e208698e962 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -418,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             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 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
 
         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<ty::Predicate<'tcx>>,
+    predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
 ) -> Vec<ty::Region<'tcx>> {
-    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 052de4a4e5b..6326a87c5ed 100644
--- a/src/librustc_trait_selection/traits/auto_trait.rs
+++ b/src/librustc_trait_selection/traits/auto_trait.rs
@@ -281,7 +281,7 @@ impl AutoTraitFinder<'tcx> {
             },
         }));
 
-        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 @@ impl AutoTraitFinder<'tcx> {
                 _ => 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 @@ impl AutoTraitFinder<'tcx> {
                             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 35eb5d73ada..fa2af24c945 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 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, '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 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         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 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                             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 f8fc155f582..c5dbe816295 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<Item = PredicateObligation<'tcx>> {
     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 d9fba1fd783..96b2b904e65 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 4d02c5eb230..2b4a0409fd1 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<Item = ty::Predicate<'tcx>>,
-{
+    env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+) {
     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 45fda3004b0..dfbb0742448 100644
--- a/src/librustc_trait_selection/traits/select.rs
+++ b/src/librustc_trait_selection/traits/select.rs
@@ -1443,7 +1443,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             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 beebddd72a8..897ac0d736e 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 ffece42ec30..4aceccf64ce 100644
--- a/src/librustc_trait_selection/traits/util.rs
+++ b/src/librustc_trait_selection/traits/util.rs
@@ -81,12 +81,10 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
 
 pub fn expand_trait_aliases<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
+    trait_refs: impl Iterator<Item = (ty::PolyTraitRef<'tcx>, 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<PredicateObligation<'tcx>>) {
+) -> (ty::TraitRef<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
     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<PredicateObligation<'tcx>> {
+    generic_bounds: ty::InstantiatedPredicates<'tcx>,
+) -> impl Iterator<Item = PredicateObligation<'tcx>> {
     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 f6953971ef5..7eabdf706ef 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<Item = ty::AssocItem>,
+    mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
 ) {
     debug!(
         "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
@@ -232,35 +232,34 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
         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 23c7954d088..64dc34ab3b0 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -114,7 +114,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // 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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         &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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             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 90a9f8a4d6f..ae2061a2e3f 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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 3f159fe5e30..03e32c21a54 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1342,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             // 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 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
                     // 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 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                             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 d631d3c3340..fc96a26a2c7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3460,7 +3460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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 ffe1dcbd444..7eb8bf7c6be 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 c7ef07bde30..8b12535b3a2 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<D: Debug> 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() {