diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 84547dca45363..add2df25884e3 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -85,10 +85,10 @@ impl GenericParamDef { ) -> Option>> { match self.kind { GenericParamDefKind::Type { has_default, .. } if has_default => { - Some(EarlyBinder(tcx.type_of(self.def_id).into())) + Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into())) } GenericParamDefKind::Const { has_default } if has_default => { - Some(EarlyBinder(tcx.const_param_default(self.def_id).into())) + Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into())) } _ => None, } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 815e39aab5715..e32e4c4f26efa 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -932,6 +932,10 @@ impl EarlyBinder { let value = f(self.0)?; Ok(EarlyBinder(value)) } + + pub fn rebind(&self, value: U) -> EarlyBinder { + EarlyBinder(value) + } } impl EarlyBinder> { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 0e581d7f1f7ed..923161bcfe9d3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -676,6 +676,10 @@ impl<'tcx> TyCtxt<'tcx> { ) -> ty::EarlyBinder<&'tcx ty::List>> { ty::EarlyBinder(self.item_bounds(def_id)) } + + pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder> { + ty::EarlyBinder(self.const_param_default(def_id)) + } } struct OpaqueTypeExpander<'tcx> { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 3be1783ae3389..f3153a6482048 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -537,13 +537,12 @@ fn build_call_shim<'tcx>( }; let def_id = instance.def_id(); - let sig = tcx.fn_sig(def_id); - let mut sig = tcx.erase_late_bound_regions(sig); + let sig = tcx.bound_fn_sig(def_id); + let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig)); assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body()); - if let Some(sig_substs) = sig_substs { - sig = EarlyBinder(sig).subst(tcx, sig_substs); - } + let mut sig = + if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 }; if let CallKind::Indirect(fnty) = call_kind { // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e1131140c39e8..4862631980e36 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -12,7 +12,7 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, EarlyBinder, GenericParamDefKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; @@ -555,7 +555,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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); + bound.map_bound(|b| b.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( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 0a2b54eec47cd..1d4e64b6bfc30 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -550,7 +550,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - EarlyBinder(tcx.const_param_default(param.def_id)) + tcx.bound_const_param_default(param.def_id) .subst(tcx, substs.unwrap()) .into() } else { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f3341e72e7362..7d4c3f1e31bdf 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1426,7 +1426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default } => { if !infer_args && has_default { - EarlyBinder(tcx.const_param_default(param.def_id)) + tcx.bound_const_param_default(param.def_id) .subst(tcx, substs.unwrap()) .into() } else { diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index e9b91414a07ab..2de225303560c 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -21,9 +21,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{ - self, EarlyBinder, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable, -}; +use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{ @@ -713,7 +711,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let impl_ty = EarlyBinder(impl_ty).subst(self.tcx, impl_substs); + let impl_ty = impl_ty.subst(self.tcx, impl_substs); debug!("impl_ty: {:?}", impl_ty); @@ -1811,9 +1809,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.erase_late_bound_regions(xform_fn_sig) } - /// Gets the type of an impl and generate substitutions with placeholders. - fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, SubstsRef<'tcx>) { - (self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id)) + /// Gets the type of an impl and generate substitutions with inference vars. + fn impl_ty_and_substs( + &self, + impl_def_id: DefId, + ) -> (ty::EarlyBinder>, SubstsRef<'tcx>) { + (self.tcx.bound_type_of(impl_def_id), self.fresh_item_substs(impl_def_id)) } fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> { diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index bbf31de527eb3..7534482cce9bb 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -6,7 +6,7 @@ use super::utils::*; #[derive(Debug)] pub struct ExplicitPredicatesMap<'tcx> { - map: FxHashMap>, + map: FxHashMap>>, } impl<'tcx> ExplicitPredicatesMap<'tcx> { @@ -14,11 +14,11 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { ExplicitPredicatesMap { map: FxHashMap::default() } } - pub fn explicit_predicates_of( + pub(crate) fn explicit_predicates_of( &mut self, tcx: TyCtxt<'tcx>, def_id: DefId, - ) -> &RequiredPredicates<'tcx> { + ) -> &ty::EarlyBinder> { self.map.entry(def_id).or_insert_with(|| { let predicates = if def_id.is_local() { tcx.explicit_predicates_of(def_id) @@ -63,7 +63,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { } } - required_predicates + ty::EarlyBinder(required_predicates) }) } } diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 52f9e386441a4..257a9520eeb25 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; -use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use super::explicit::ExplicitPredicatesMap; @@ -13,20 +13,19 @@ use super::utils::*; /// `global_inferred_outlives`: this is initially the empty map that /// was generated by walking the items in the crate. This will /// now be filled with inferred predicates. -pub fn infer_predicates<'tcx>( +pub(super) fn infer_predicates<'tcx>( tcx: TyCtxt<'tcx>, - explicit_map: &mut ExplicitPredicatesMap<'tcx>, -) -> FxHashMap> { +) -> FxHashMap>> { debug!("infer_predicates"); - let mut predicates_added = true; + let mut explicit_map = ExplicitPredicatesMap::new(); let mut global_inferred_outlives = FxHashMap::default(); // If new predicates were added then we need to re-calculate // all crates since there could be new implied predicates. - while predicates_added { - predicates_added = false; + 'outer: loop { + let mut predicates_added = false; // Visit all the crates and infer predicates for id in tcx.hir().items() { @@ -53,9 +52,9 @@ pub fn infer_predicates<'tcx>( tcx, field_ty, field_span, - &mut global_inferred_outlives, + &global_inferred_outlives, &mut item_required_predicates, - explicit_map, + &mut explicit_map, ); } } @@ -70,12 +69,17 @@ pub fn infer_predicates<'tcx>( // we walk the crates again and re-calculate predicates for all // items. let item_predicates_len: usize = - global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len()); + global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.0.len()); if item_required_predicates.len() > item_predicates_len { predicates_added = true; - global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates); + global_inferred_outlives + .insert(item_did.to_def_id(), ty::EarlyBinder(item_required_predicates)); } } + + if !predicates_added { + break 'outer; + } } global_inferred_outlives @@ -85,7 +89,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, field_ty: Ty<'tcx>, field_span: Span, - global_inferred_outlives: &FxHashMap>, + global_inferred_outlives: &FxHashMap>>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { @@ -133,11 +137,13 @@ fn insert_required_predicates_to_be_wf<'tcx>( // 'a` holds for `Foo`. debug!("Adt"); if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) { - for (unsubstituted_predicate, &span) in unsubstituted_predicates { + for (unsubstituted_predicate, &span) in &unsubstituted_predicates.0 { // `unsubstituted_predicate` is `U: 'b` in the // example above. So apply the substitution to // get `T: 'a` (or `predicate`): - let predicate = EarlyBinder(*unsubstituted_predicate).subst(tcx, substs); + let predicate = unsubstituted_predicates + .rebind(*unsubstituted_predicate) + .subst(tcx, substs); insert_outlives_predicate( tcx, predicate.0, @@ -224,7 +230,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( /// will give us `U: 'static` and `U: Foo`. The latter we /// can ignore, but we will want to process `U: 'static`, /// applying the substitution as above. -pub fn check_explicit_predicates<'tcx>( +fn check_explicit_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, substs: &[GenericArg<'tcx>], @@ -242,7 +248,7 @@ pub fn check_explicit_predicates<'tcx>( ); let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); - for (outlives_predicate, &span) in explicit_predicates { + for (outlives_predicate, &span) in &explicit_predicates.0 { debug!("outlives_predicate = {:?}", &outlives_predicate); // Careful: If we are inferring the effects of a `dyn Trait<..>` @@ -287,7 +293,7 @@ pub fn check_explicit_predicates<'tcx>( continue; } - let predicate = EarlyBinder(*outlives_predicate).subst(tcx, substs); + let predicate = explicit_predicates.rebind(*outlives_predicate).subst(tcx, substs); debug!("predicate = {:?}", &predicate); insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates); } diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index dccfee19960c5..8fa65d51e3ba1 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -88,9 +88,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { // for the type. // Compute the inferred predicates - let mut exp_map = explicit::ExplicitPredicatesMap::new(); - - let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map); + let global_inferred_outlives = implicit_infer::infer_predicates(tcx); // Convert the inferred predicates into the "collected" form the // global data structure expects. @@ -100,7 +98,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { let predicates = global_inferred_outlives .iter() .map(|(&def_id, set)| { - let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map( + let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map( |(ty::OutlivesPredicate(kind1, region2), &span)| { match kind1.unpack() { GenericArgKind::Type(ty1) => Some(( diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index 14e3048cadc62..b718ca9421336 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -7,12 +7,12 @@ use std::collections::BTreeMap; /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred /// must be added to the struct header. -pub type RequiredPredicates<'tcx> = +pub(crate) type RequiredPredicates<'tcx> = BTreeMap, ty::Region<'tcx>>, Span>; /// Given a requirement `T: 'a` or `'b: 'a`, deduce the /// outlives_component and add it to `required_predicates` -pub fn insert_outlives_predicate<'tcx>( +pub(crate) fn insert_outlives_predicate<'tcx>( tcx: TyCtxt<'tcx>, kind: GenericArg<'tcx>, outlived_region: Region<'tcx>,