about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs31
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs5
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs12
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs3
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs16
9 files changed, 59 insertions, 57 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 60eaad9b498..3469ec4767b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -664,10 +664,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
             });
             self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
             // Recurse into bounds
-            for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
-                let pred_span = pred.0.1;
-
-                let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
+            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     ObligationCause::misc(self.span, self.body_id),
@@ -1752,15 +1749,10 @@ pub fn check_type_bounds<'tcx>(
 
     let obligations = tcx
         .bound_explicit_item_bounds(trait_ty.def_id)
-        .transpose_iter()
-        .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-        .map(|(bound, span)| {
-            debug!(?bound);
-            // this is where opaque type is found
-            let concrete_ty_bound = bound.subst(tcx, rebased_substs);
+        .subst_iter_copied(tcx, rebased_substs)
+        .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
-
-            traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
+            traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
         })
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index c22d828625b..2b15d4dcd08 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 for ty in [first_ty, second_ty] {
-                    for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() {
-                        let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs);
+                    for (pred, _) in self
+                        .tcx
+                        .bound_explicit_item_bounds(rpit_def_id)
+                        .subst_iter_copied(self.tcx, substs)
+                    {
                         let pred = match pred.kind().skip_binder() {
                             ty::PredicateKind::Trait(mut trait_pred) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index de5b4a50218..a5a45f75e0e 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -176,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match *expected_ty.kind() {
             ty::Opaque(def_id, substs) => {
                 let bounds = self.tcx.bound_explicit_item_bounds(def_id);
-                let sig = bounds
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .find_map(|(pred, span)| match pred.0.kind().skip_binder() {
+                let sig =
+                    bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
+                        .kind()
+                        .skip_binder()
+                    {
                         ty::PredicateKind::Projection(proj_predicate) => self
                             .deduce_sig_from_projection(
-                                Some(span.0),
-                                pred.0
-                                    .kind()
-                                    .rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
+                                Some(span),
+                                pred.kind().rebind(proj_predicate),
                             ),
                         _ => None,
                     });
 
                 let kind = bounds
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
+                    .0
+                    .iter()
+                    .filter_map(|(pred, _)| match pred.kind().skip_binder() {
                         ty::PredicateKind::Trait(tp) => {
                             self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
                         }
@@ -697,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Opaque(def_id, substs) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
-                .transpose_iter()
-                .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
+                .subst_iter_copied(self.tcx, substs)
+                .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
             ty::Projection(proj)
                 if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 self.tcx
                     .bound_explicit_item_bounds(proj.item_def_id)
-                    .transpose_iter()
-                    .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                    .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
+                    .subst_iter_copied(self.tcx, proj.substs)
+                    .find_map(|(p, s)| get_future_output(p, s))?
             }
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ddeeaa9618e..2fe6f63a9c6 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -338,8 +338,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
             let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
 
-            for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-                let predicate = predicate.subst(self.tcx, substs);
+            for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) {
                 let output = predicate
                     .kind()
                     .map_bound(|kind| match kind {
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 77e8f72aefa..80ecd737829 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -543,10 +543,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
 
-        for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-            debug!(?predicate);
-            let predicate = predicate.subst(tcx, substs);
-
+        for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
                 ty_op: |ty| match *ty.kind() {
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 81b9f55e703..e0958b039dc 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -91,14 +91,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
             // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
             // with `impl Send: OtherTrait`.
-            for assoc_pred_and_span in
-                cx.tcx.bound_explicit_item_bounds(proj.projection_ty.item_def_id).transpose_iter()
+            for (assoc_pred, assoc_pred_span) in cx
+                .tcx
+                .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+                .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
             {
-                let assoc_pred_span = assoc_pred_and_span.0.1;
-                let assoc_pred = assoc_pred_and_span
-                    .map_bound(|(pred, _)| *pred)
-                    .subst(cx.tcx, &proj.projection_ty.substs)
-                    .fold_with(proj_replacer);
+                let assoc_pred = assoc_pred.fold_with(proj_replacer);
                 let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
                     continue;
                 };
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 0b06ccc19ec..f18c95a61d4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -795,8 +795,7 @@ pub trait PrettyPrinter<'tcx>:
         let mut fn_traits = FxIndexMap::default();
         let mut is_sized = false;
 
-        for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-            let predicate = predicate.subst(tcx, substs);
+        for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index c9930e8ad0a..0660e9b79a7 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::visit::{TypeVisitable, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::{Interned, WithStableHash};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
@@ -558,6 +559,28 @@ impl<T, U> EarlyBinder<(T, U)> {
     }
 }
 
+impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
+    pub fn subst_iter(
+        self,
+        tcx: TyCtxt<'tcx>,
+        substs: &'s [GenericArg<'tcx>],
+    ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
+        self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
+    }
+}
+
+impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
+    EarlyBinder<T>
+{
+    pub fn subst_iter_copied(
+        self,
+        tcx: TyCtxt<'tcx>,
+        substs: &'s [GenericArg<'tcx>],
+    ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
+        self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
+    }
+}
+
 pub struct EarlyBinderIter<T> {
     t: T,
 }
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index a15daec7c3c..3b5a9ba8356 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -657,21 +657,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
     let mut output = None;
     let lang_items = cx.tcx.lang_items();
 
-    for pred in cx
+    for (pred, _) in cx
         .tcx
         .bound_explicit_item_bounds(ty.item_def_id)
-        .transpose_iter()
-        .map(|x| x.map_bound(|(p, _)| p))
+        .subst_iter_copied(cx.tcx, ty.substs)
     {
-        match pred.0.kind().skip_binder() {
+        match pred.kind().skip_binder() {
             PredicateKind::Trait(p)
                 if (lang_items.fn_trait() == Some(p.def_id())
                     || lang_items.fn_mut_trait() == Some(p.def_id())
                     || lang_items.fn_once_trait() == Some(p.def_id())) =>
             {
-                let i = pred
-                    .map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
-                    .subst(cx.tcx, ty.substs);
+                let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));
 
                 if inputs.map_or(false, |inputs| inputs != i) {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -684,10 +681,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
-                output = Some(
-                    pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
-                        .subst(cx.tcx, ty.substs),
-                );
+                output = pred.kind().rebind(p.term.ty()).transpose();
             },
             _ => (),
         }