diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 2a5b7e936ca..02caae7a90a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1849,10 +1849,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Future::Output let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; - let bounds = self.tcx.explicit_item_bounds(*def_id); + let bounds = self.tcx.bound_explicit_item_bounds(*def_id); - for (predicate, _) in bounds { - let predicate = EarlyBinder(*predicate).subst(self.tcx, substs); + for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { + let predicate = predicate.subst(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 6b2c599864c..92c0ed84057 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -9,7 +9,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{ - self, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor, + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor, }; use rustc_span::Span; @@ -561,11 +561,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations; } - let item_bounds = tcx.explicit_item_bounds(def_id); + let item_bounds = tcx.bound_explicit_item_bounds(def_id); - for (predicate, _) in item_bounds { + for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { debug!(?predicate); - let predicate = EarlyBinder(*predicate).subst(tcx, substs); + let predicate = predicate.subst(tcx, substs); let predicate = predicate.fold_with(&mut BottomUpFolder { tcx, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e680250e7b1..4c0bc2e4337 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,8 +1,6 @@ use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; -use crate::ty::{ - self, ConstInt, DefIdTree, EarlyBinder, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable, -}; +use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sso::SsoHashSet; @@ -776,14 +774,14 @@ pub trait PrettyPrinter<'tcx>: // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().explicit_item_bounds(def_id); + let bounds = self.tcx().bound_explicit_item_bounds(def_id); let mut traits = BTreeMap::new(); let mut fn_traits = BTreeMap::new(); let mut is_sized = false; - for (predicate, _) in bounds { - let predicate = EarlyBinder(*predicate).subst(self.tcx(), substs); + for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { + let predicate = predicate.subst(self.tcx(), substs); let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ca8528b3350..a973a5c9b50 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1109,6 +1109,30 @@ impl EarlyBinder> { } } +impl EarlyBinder<(T, U)> { + pub fn transpose_tuple2(self) -> (EarlyBinder, EarlyBinder) { + (EarlyBinder(self.0.0), EarlyBinder(self.0.1)) + } +} + +pub struct EarlyBinderIter { + t: T, +} + +impl EarlyBinder { + pub fn transpose_iter(self) -> EarlyBinderIter { + EarlyBinderIter { t: self.0.into_iter() } + } +} + +impl Iterator for EarlyBinderIter { + type Item = EarlyBinder; + + fn next(&mut self) -> Option { + self.t.next().map(|i| EarlyBinder(i)) + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index ed0f6a7ccd1..9c345c76d0e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -604,6 +604,20 @@ impl<'tcx> TyCtxt<'tcx> { pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option>> { self.impl_trait_ref(def_id).map(|i| EarlyBinder(i)) } + + pub fn bound_explicit_item_bounds( + self, + def_id: DefId, + ) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { + EarlyBinder(self.explicit_item_bounds(def_id)) + } + + pub fn bound_item_bounds( + self, + def_id: DefId, + ) -> EarlyBinder<&'tcx ty::List>> { + EarlyBinder(self.item_bounds(def_id)) + } } struct OpaqueTypeExpander<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 004091661fa..beaa56e1c1c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1276,10 +1276,8 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // Check whether the self-type is itself a projection. // If so, extract what we know from the trait and try to come up with a good answer. let bounds = match *obligation.predicate.self_ty().kind() { - ty::Projection(ref data) => { - EarlyBinder(tcx.item_bounds(data.item_def_id)).subst(tcx, data.substs) - } - ty::Opaque(def_id, substs) => EarlyBinder(tcx.item_bounds(def_id)).subst(tcx, substs), + ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs), + ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs), ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index fe80d02595a..b9025c98fe7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -174,7 +174,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), }; - let candidate_predicate = EarlyBinder(tcx.item_bounds(def_id)[idx]).subst(tcx, substs); + let candidate_predicate = + tcx.bound_item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs); let candidate = candidate_predicate .to_opt_poly_trait_pred() .expect("projection candidate is not a trait predicate") @@ -500,21 +501,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This maybe belongs in wf, but that can't (doesn't) handle // higher-ranked things. // Prevent, e.g., `dyn Iterator`. - for bound in self.tcx().item_bounds(assoc_type) { - let subst_bound = if defs.count() == 0 { - EarlyBinder(bound).subst(tcx, trait_predicate.trait_ref.substs) - } else { - let mut substs = smallvec::SmallVec::with_capacity(defs.count()); - substs.extend(trait_predicate.trait_ref.substs.iter()); - let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = - smallvec::SmallVec::with_capacity( - bound.kind().bound_vars().len() + defs.count(), - ); - bound_vars.extend(bound.kind().bound_vars().into_iter()); - InternalSubsts::fill_single( - &mut substs, - defs, - &mut |param, _| match param.kind { + for bound in self.tcx().bound_item_bounds(assoc_type).transpose_iter() { + let subst_bound = + if defs.count() == 0 { + bound.subst(tcx, trait_predicate.trait_ref.substs) + } else { + let mut substs = smallvec::SmallVec::with_capacity(defs.count()); + substs.extend(trait_predicate.trait_ref.substs.iter()); + let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = + smallvec::SmallVec::with_capacity( + bound.0.kind().bound_vars().len() + defs.count(), + ); + bound_vars.extend(bound.0.kind().bound_vars().into_iter()); + InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param + .kind + { GenericParamDefKind::Type { .. } => { let kind = ty::BoundTyKind::Param(param.name); let bound_var = ty::BoundVariableKind::Ty(kind); @@ -553,15 +554,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .into() } - }, - ); - let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); - let assoc_ty_substs = tcx.intern_substs(&substs); + }); + let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let assoc_ty_substs = tcx.intern_substs(&substs); - let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); - let bound = EarlyBinder(bound.kind().skip_binder()).subst(tcx, assoc_ty_substs); - tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars)) - }; + let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let bound = + EarlyBinder(bound.0.kind().skip_binder()).subst(tcx, assoc_ty_substs); + tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars)) + }; let normalized_bound = normalize_with_depth_to( self, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ab617d16cc4..4f797b182c0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1341,7 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } }; - let bounds = EarlyBinder(tcx.item_bounds(def_id)).subst(tcx, substs); + let bounds = tcx.bound_item_bounds(def_id).subst(tcx, substs); // The bounds returned by `item_bounds` may contain duplicates after // normalization, so try to deduplicate when possible to avoid diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 663a644a9e7..2ff32bdf978 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2447,10 +2447,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { true, None, ); - self.normalize_ty( - span, - EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs), - ) + EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) + .subst(tcx, substs) } hir::TyKind::Array(ref ty, ref length) => { let length = match length { diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index df10853bf50..c8fe0468736 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -12,7 +12,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, EarlyBinder, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_span::DUMMY_SP; use rustc_target::spec::abi::Abi; @@ -175,19 +175,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Option>, Option) { match *expected_ty.kind() { ty::Opaque(def_id, substs) => { - let bounds = self.tcx.explicit_item_bounds(def_id); - let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() { - ty::PredicateKind::Projection(proj_predicate) => self - .deduce_sig_from_projection( - Some(*span), - pred.kind().rebind(EarlyBinder(proj_predicate).subst(self.tcx, substs)), - ), - _ => None, - }); + 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() { + ty::PredicateKind::Projection(proj_predicate) => self + .deduce_sig_from_projection( + Some(span.0), + pred.0.kind().rebind( + pred.map_bound(|_| proj_predicate).subst(self.tcx, substs), + ), + ), + _ => None, + }); let kind = bounds - .iter() - .filter_map(|(pred, _)| match pred.kind().skip_binder() { + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .filter_map(|(pred, _)| match pred.0.kind().skip_binder() { ty::PredicateKind::Trait(tp) => { self.tcx.fn_trait_kind_from_lang_item(tp.def_id()) } @@ -668,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), }; - let item_bounds = self.tcx.explicit_item_bounds(def_id); + let item_bounds = self.tcx.bound_explicit_item_bounds(def_id); // Search for a pending obligation like // @@ -676,17 +682,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // where R is the return type we are expecting. This type `T` // will be our output. - let output_ty = item_bounds.iter().find_map(|&(predicate, span)| { - let bound_predicate = EarlyBinder(predicate).subst(self.tcx, substs).kind(); - if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { - self.deduce_future_output_from_projection( - span, - bound_predicate.rebind(proj_predicate), - ) - } else { - None - } - }); + let output_ty = item_bounds + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .find_map(|(predicate, span)| { + let bound_predicate = predicate.subst(self.tcx, substs).kind(); + if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() + { + self.deduce_future_output_from_projection( + span.0, + bound_predicate.rebind(proj_predicate), + ) + } else { + None + } + }); debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty); output_ty diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 06304d8d7e7..b857679520b 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -10,7 +10,7 @@ use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::{self, DefIdTree, EarlyBinder}; +use rustc_middle::ty::{self, DefIdTree}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -1451,14 +1451,15 @@ pub fn check_type_bounds<'tcx>( }; let obligations = tcx - .explicit_item_bounds(trait_ty.def_id) - .iter() - .map(|&(bound, span)| { + .bound_explicit_item_bounds(trait_ty.def_id) + .transpose_iter() + .map(|e| e.map_bound(|e| *e).transpose_tuple2()) + .map(|(bound, span)| { debug!(?bound); - let concrete_ty_bound = EarlyBinder(bound).subst(tcx, rebased_substs); + let concrete_ty_bound = bound.subst(tcx, rebased_substs); debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) + traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound) }) .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations);