diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index e6f996491a41b..2259a59e1956c 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -60,13 +60,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Replace the bound items in the fn sig with fresh // variables, so that they represent the view from // "inside" the closure. - self.infcx - .replace_bound_vars_with_fresh_vars( - body.span, - LateBoundRegionConversionTime::FnCall, - poly_sig, - ) - .0 + self.infcx.replace_bound_vars_with_fresh_vars( + body.span, + LateBoundRegionConversionTime::FnCall, + poly_sig, + ) }, ); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index e5aed1b60ddc1..e405baf7575dd 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -20,7 +20,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin, + InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, }; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; @@ -1436,11 +1436,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return; } }; - let (sig, map) = self.infcx.replace_bound_vars_with_fresh_vars( - term.source_info.span, - LateBoundRegionConversionTime::FnCall, - sig, - ); + let (sig, map) = tcx.replace_late_bound_regions(sig, |br| { + self.infcx.next_region_var(LateBoundRegion( + term.source_info.span, + br.kind, + LateBoundRegionConversionTime::FnCall, + )) + }); debug!(?sig); let sig = self.normalize(sig, term_location); self.check_call_dest(body, term, &sig, *destination, target, term_location); diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs index 553a11d4393f9..45ed4b63009b4 100644 --- a/compiler/rustc_infer/src/infer/canonical/substitute.rs +++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs @@ -86,6 +86,6 @@ where c => bug!("{:?} is a const but value is {:?}", bound_ct, c), }; - tcx.replace_escaping_bound_vars(value, fld_r, fld_t, fld_c) + tcx.replace_escaping_bound_vars_uncached(value, fld_r, fld_t, fld_c) } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index ef6d464d3c6f1..3b1798ca73746 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -153,12 +153,12 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { { if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() { self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; - self.fields.higher_ranked_sub(b, a, self.a_is_expected) + self.fields.higher_ranked_sub(b, a, self.a_is_expected)?; } else { // Fast path for the common case. self.relate(a.skip_binder(), b.skip_binder())?; - Ok(a) } + Ok(a) } } diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 73cc411e533d3..bb3b410b2bde3 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -3,78 +3,85 @@ use super::combine::CombineFields; use super::{HigherRankedType, InferCtxt}; - use crate::infer::CombinedSnapshot; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { + /// Checks whether `for<..> sub <: for<..> sup` holds. + /// + /// For this to hold, **all** instantiations of the super type + /// have to be a super type of **at least one** instantiation of + /// the subtype. + /// + /// This is implemented by first entering a new universe. + /// We then replace all bound variables in `sup` with placeholders, + /// and all bound variables in `sup` with inference vars. + /// We can then just relate the two resulting types as normal. + /// + /// Note: this is a subtle algorithm. For a full explanation, please see + /// the [rustc dev guide][rd] + /// + /// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html #[instrument(skip(self), level = "debug")] pub fn higher_ranked_sub( &mut self, - a: Binder<'tcx, T>, - b: Binder<'tcx, T>, - a_is_expected: bool, - ) -> RelateResult<'tcx, Binder<'tcx, T>> + sub: Binder<'tcx, T>, + sup: Binder<'tcx, T>, + sub_is_expected: bool, + ) -> RelateResult<'tcx, ()> where T: Relate<'tcx>, { - // Rather than checking the subtype relationship between `a` and `b` - // as-is, we need to do some extra work here in order to make sure - // that function subtyping works correctly with respect to regions - // - // Note: this is a subtle algorithm. For a full explanation, please see - // the rustc dev guide: - // - let span = self.trace.cause.span; self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. - let b_prime = self.infcx.replace_bound_vars_with_placeholders(b); + // fresh placeholder region. Note that this automatically creates + // a new universe if needed. + let sup_prime = self.infcx.replace_bound_vars_with_placeholders(sup); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- // but no other pre-existing region variables -- can name // the placeholders. - let (a_prime, _) = - self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); + let sub_prime = + self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, sub); - debug!("a_prime={:?}", a_prime); - debug!("b_prime={:?}", b_prime); + debug!("a_prime={:?}", sub_prime); + debug!("b_prime={:?}", sup_prime); // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(a_prime, b_prime)?; - - debug!("higher_ranked_sub: OK result={:?}", result); + let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; - // We related `a_prime` and `b_prime`, which just had any bound vars - // replaced with placeholders or infer vars, respectively. Relating - // them should not introduce new bound vars. - Ok(ty::Binder::dummy(result)) + debug!("higher_ranked_sub: OK result={result:?}"); + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. + Ok(()) }) } } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Replaces all bound variables (lifetimes, types, and constants) bound by - /// `binder` with placeholder variables. + /// `binder` with placeholder variables in a new universe. This means that the + /// new placeholders can only be named by inference variables created after + /// this method has been called. /// /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self))] pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T where - T: TypeFoldable<'tcx>, + T: TypeFoldable<'tcx> + Copy, { - // Figure out what the next universe will be, but don't actually create - // it until after we've done the substitution (in particular there may - // be no bound variables). This is a performance optimization, since the - // leak check for example can be skipped if no new universes are created - // (i.e., if there are no placeholders). - let next_universe = self.universe().next_universe(); + if let Some(inner) = binder.no_bound_vars() { + return inner; + } + + let next_universe = self.create_next_universe(); let fld_r = |br: ty::BoundRegion| { self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion { @@ -100,23 +107,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) }; - let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c); - - // If there were higher-ranked regions to replace, then actually create - // the next universe (this avoids needlessly creating universes). - if !map.is_empty() { - let n_u = self.create_next_universe(); - assert_eq!(n_u, next_universe); - } - - debug!( - "replace_bound_vars_with_placeholders(\ - next_universe={:?}, \ - result={:?}, \ - map={:?})", - next_universe, result, map, - ); - + let result = self.tcx.replace_bound_vars_uncached(binder, fld_r, fld_t, fld_c); + debug!(?next_universe, ?result); result } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 21208933d4340..0e30b136622a0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -33,7 +33,6 @@ use rustc_span::symbol::Symbol; use rustc_span::Span; use std::cell::{Cell, Ref, RefCell}; -use std::collections::BTreeMap; use std::fmt; use self::combine::CombineFields; @@ -1524,25 +1523,40 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span: Span, lbrct: LateBoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> (T, BTreeMap>) + ) -> T where - T: TypeFoldable<'tcx>, + T: TypeFoldable<'tcx> + Copy, { - let fld_r = - |br: ty::BoundRegion| self.next_region_var(LateBoundRegion(span, br.kind, lbrct)); - let fld_t = |_| { - self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, + if let Some(inner) = value.no_bound_vars() { + return inner; + } + + let mut region_map = FxHashMap::default(); + let fld_r = |br: ty::BoundRegion| { + *region_map + .entry(br) + .or_insert_with(|| self.next_region_var(LateBoundRegion(span, br.kind, lbrct))) + }; + + let mut ty_map = FxHashMap::default(); + let fld_t = |bt: ty::BoundTy| { + *ty_map.entry(bt).or_insert_with(|| { + self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }) }) }; - let fld_c = |_, ty| { - self.next_const_var( - ty, - ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span }, - ) + let mut ct_map = FxHashMap::default(); + let fld_c = |bc: ty::BoundVar, ty| { + *ct_map.entry(bc).or_insert_with(|| { + self.next_const_var( + ty, + ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span }, + ) + }) }; - self.tcx.replace_bound_vars(value, fld_r, fld_t, fld_c) + self.tcx.replace_bound_vars_uncached(value, fld_r, fld_t, fld_c) } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 3600b54a27104..d0c6d8d16ebfa 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -198,7 +198,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { where T: Relate<'tcx>, { - self.fields.higher_ranked_sub(a, b, self.a_is_expected) + self.fields.higher_ranked_sub(a, b, self.a_is_expected)?; + Ok(a) } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 5469aeb4c2ce0..5ccf735f1d2a2 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -656,17 +656,17 @@ struct BoundVarReplacer<'a, 'tcx> { /// the ones we have visited. current_index: ty::DebruijnIndex, - fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>, - fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>, - fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>, + fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), + fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), + fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a), } impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> { fn new( tcx: TyCtxt<'tcx>, - fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>, - fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>, - fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>, + fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), + fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), + fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a), ) -> Self { BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c } } @@ -690,55 +690,42 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { - if let Some(fld_t) = self.fld_t.as_mut() { - let ty = fld_t(bound_ty); - return ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()); - } - } - _ if t.has_vars_bound_at_or_above(self.current_index) => { - return t.super_fold_with(self); + let ty = (self.fld_t)(bound_ty); + ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()) } - _ => {} + _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), + _ => t, } - t } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { - if let Some(fld_r) = self.fld_r.as_mut() { - let region = fld_r(br); - return if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, - // that region should always use the INNERMOST - // debruijn index. Then we adjust it to the - // correct depth. - assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(debruijn, br)) - } else { - region - }; + let region = (self.fld_r)(br); + if let ty::ReLateBound(debruijn1, br) = *region { + // If the callback returns a late-bound region, + // that region should always use the INNERMOST + // debruijn index. Then we adjust it to the + // correct depth. + assert_eq!(debruijn1, ty::INNERMOST); + self.tcx.mk_region(ty::ReLateBound(debruijn, br)) + } else { + region } } - _ => {} + _ => r, } - r } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.val() { ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { - if let Some(fld_c) = self.fld_c.as_mut() { - let ct = fld_c(bound_const, ct.ty()); - return ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()); - } + let ct = (self.fld_c)(bound_const, ct.ty()); + ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()) } - _ if ct.has_vars_bound_at_or_above(self.current_index) => { - return ct.super_fold_with(self); - } - _ => {} + _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self), + _ => ct, } - ct } } @@ -752,8 +739,10 @@ impl<'tcx> TyCtxt<'tcx> { /// returned at the end with each bound region and the free region /// that replaced it. /// - /// This method only replaces late bound regions and the result may still - /// contain escaping bound types. + /// # Panics + /// + /// This method only replaces late bound regions. Any types or + /// constants bound by `value` will cause an ICE. pub fn replace_late_bound_regions( self, value: Binder<'tcx, T>, @@ -764,22 +753,35 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { let mut region_map = BTreeMap::new(); - let mut real_fld_r = - |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); + let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); + let value = self.replace_late_bound_regions_uncached(value, real_fld_r); + (value, region_map) + } + + pub fn replace_late_bound_regions_uncached( + self, + value: Binder<'tcx, T>, + mut fld_r: F, + ) -> T + where + F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + T: TypeFoldable<'tcx>, + { + let mut fld_t = |b| bug!("unexpected bound ty in binder: {b:?}"); + let mut fld_c = |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"); let value = value.skip_binder(); - let value = if !value.has_escaping_bound_vars() { + if !value.has_escaping_bound_vars() { value } else { - let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None); + let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c); value.fold_with(&mut replacer) - }; - (value, region_map) + } } /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping /// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c` /// closure replaces escaping bound consts. - pub fn replace_escaping_bound_vars( + pub fn replace_escaping_bound_vars_uncached( self, value: T, mut fld_r: F, @@ -795,32 +797,28 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_escaping_bound_vars() { value } else { - let mut replacer = - BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c)); + let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c); value.fold_with(&mut replacer) } } /// Replaces all types or regions bound by the given `Binder`. The `fld_r` - /// closure replaces bound regions while the `fld_t` closure replaces bound - /// types. - pub fn replace_bound_vars( + /// closure replaces bound regions, the `fld_t` closure replaces bound + /// types, and `fld_c` replaces bound constants. + pub fn replace_bound_vars_uncached( self, value: Binder<'tcx, T>, - mut fld_r: F, + fld_r: F, fld_t: G, fld_c: H, - ) -> (T, BTreeMap>) + ) -> T where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, G: FnMut(ty::BoundTy) -> Ty<'tcx>, H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>, T: TypeFoldable<'tcx>, { - let mut region_map = BTreeMap::new(); - let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); - let value = self.replace_escaping_bound_vars(value.skip_binder(), real_fld_r, fld_t, fld_c); - (value, region_map) + self.replace_escaping_bound_vars_uncached(value.skip_binder(), fld_r, fld_t, fld_c) } /// Replaces any late-bound regions bound in `value` with @@ -833,20 +831,19 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - self.replace_late_bound_regions(value, |br| { + self.replace_late_bound_regions_uncached(value, |br| { self.mk_region(ty::ReFree(ty::FreeRegion { scope: all_outlive_scope, bound_region: br.kind, })) }) - .0 } pub fn shift_bound_var_indices(self, bound_vars: usize, value: T) -> T where T: TypeFoldable<'tcx>, { - self.replace_escaping_bound_vars( + self.replace_escaping_bound_vars_uncached( value, |r| { self.mk_region(ty::ReLateBound( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 255b52584edc6..2e7067fa71076 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1536,7 +1536,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { let bound_predicate = predicate.kind(); if let ty::PredicateKind::Projection(data) = bound_predicate.skip_binder() { let mut selcx = SelectionContext::new(self); - let (data, _) = self.replace_bound_vars_with_fresh_vars( + let data = self.replace_bound_vars_with_fresh_vars( obligation.cause.span, infer::LateBoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9f75bdb2533e6..7341ab0ab124a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1920,7 +1920,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cause = &obligation.cause; let param_env = obligation.param_env; - let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars( + let cache_entry = infcx.replace_bound_vars_with_fresh_vars( cause.span, LateBoundRegionConversionTime::HigherRankedType, poly_cache_entry, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 34dc81b14d29e..cbf29af1c554e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -421,14 +421,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let object_trait_ref = data.principal().unwrap_or_else(|| { span_bug!(obligation.cause.span, "object candidate with no principal") }); - let object_trait_ref = self - .infcx - .replace_bound_vars_with_fresh_vars( - obligation.cause.span, - HigherRankedType, - object_trait_ref, - ) - .0; + let object_trait_ref = self.infcx.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + object_trait_ref, + ); let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty); let mut nested = vec![]; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c7ebc194ea5ae..a484b594418c2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1453,7 +1453,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { potentially_unnormalized_candidates: bool, ) -> ProjectionMatchesProjection { let mut nested_obligations = Vec::new(); - let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars( + let infer_predicate = self.infcx.replace_bound_vars_with_fresh_vars( obligation.cause.span, LateBoundRegionConversionTime::HigherRankedType, env_predicate, diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 0a84d41b4f31c..af1288b6523be 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -152,13 +152,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(substs).is_none() { let closure_sig = substs.as_closure().sig(); - let closure_sig = self - .replace_bound_vars_with_fresh_vars( - call_expr.span, - infer::FnCall, - closure_sig, - ) - .0; + let closure_sig = self.replace_bound_vars_with_fresh_vars( + call_expr.span, + infer::FnCall, + closure_sig, + ); let adjustments = self.adjust_steps(autoderef); self.record_deferred_call_resolution( def_id, @@ -503,8 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = - self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig).0; + let fn_sig = self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig); let fn_sig = self.normalize_associated_types_in(call_expr.span, fn_sig); // Call the generic checker. diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index c8fe046873603..05b22e174b845 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -550,7 +550,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_sigs.liberated_sig.inputs(), // `liberated_sig` is E'. ) { // Instantiate (this part of..) S to S', i.e., with fresh variables. - let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( + let supplied_ty = self.infcx.replace_bound_vars_with_fresh_vars( hir_ty.span, LateBoundRegionConversionTime::FnCall, supplied_sig.inputs().rebind(supplied_ty), @@ -563,7 +563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { all_obligations.extend(obligations); } - let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( + let supplied_output_ty = self.infcx.replace_bound_vars_with_fresh_vars( decl.output.span(), LateBoundRegionConversionTime::FnCall, supplied_sig.output(), diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 4d17307ddb968..d4e17f27c92bb 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -255,7 +255,7 @@ fn compare_predicate_entailment<'tcx>( let mut wf_tys = FxHashSet::default(); - let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars( + let impl_sig = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, tcx.fn_sig(impl_m.def_id), diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 9f82bb67bd03d..48bbd4d76ea5c 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -561,13 +561,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); - let input = self - .replace_bound_vars_with_fresh_vars( - span, - infer::LateBoundRegionConversionTime::FnCall, - fn_sig.input(i), - ) - .0; + let input = self.replace_bound_vars_with_fresh_vars( + span, + infer::LateBoundRegionConversionTime::FnCall, + fn_sig.input(i), + ); self.require_type_is_sized_deferred( input, span, @@ -581,13 +579,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Also, as we just want to check sizedness, instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let output = self - .replace_bound_vars_with_fresh_vars( - expr.span, - infer::LateBoundRegionConversionTime::FnCall, - fn_sig.output(), - ) - .0; + let output = self.replace_bound_vars_with_fresh_vars( + expr.span, + infer::LateBoundRegionConversionTime::FnCall, + fn_sig.output(), + ); self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index ce9ff61bd9e6f..fa2416d56de14 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -256,7 +256,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { item_segment: &hir::PathSegment<'_>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { - let (trait_ref, _) = self.replace_bound_vars_with_fresh_vars( + let trait_ref = self.replace_bound_vars_with_fresh_vars( span, infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id), poly_trait_ref, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 76add2fb9c285..ca55a4299eb06 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return false, }; - let sig = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, sig).0; + let sig = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, sig); let sig = self.normalize_associated_types_in(expr.span, sig); if self.can_coerce(sig.output(), expected) { let (mut sugg_call, applicability) = if sig.inputs().is_empty() { diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 7992460f5464e..4061b7cae7c78 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -572,8 +572,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T where - T: TypeFoldable<'tcx>, + T: TypeFoldable<'tcx> + Copy, { - self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value).0 + self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value) } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index d4c5caa6e9292..5ca822183556b 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -462,7 +462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // may reference those regions. let fn_sig = tcx.bound_fn_sig(def_id); let fn_sig = fn_sig.subst(self.tcx, substs); - let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig).0; + let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig); let InferOk { value, obligations: o } = if is_op { self.normalize_op_associated_types_in_as_infer_ok(span, fn_sig, opt_input_expr) diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 0edf8fac9d66b..87254b211d67b 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -905,7 +905,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.probe(|_| { let substs = self.fresh_substs_for_item(self.span, method.def_id); let fty = fty.subst(self.tcx, substs); - let (fty, _) = + let fty = self.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, fty); if let Some(self_ty) = self_ty { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 838980e08aa04..de40126e724df 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -449,8 +449,9 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { format!( "{}::", // Replace the existing lifetimes with a new named lifetime. - self.tcx - .replace_late_bound_regions(poly_trait_ref, |_| { + self.tcx.replace_late_bound_regions_uncached( + poly_trait_ref, + |_| { self.tcx.mk_region(ty::ReEarlyBound( ty::EarlyBoundRegion { def_id: item_def_id, @@ -458,8 +459,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { name: Symbol::intern(<_name), }, )) - }) - .0, + } + ), ), ), ];