From 582a369bc336b1eb3aab0cfaabf4fb4359b68492 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 17 Sep 2018 16:57:41 -0400 Subject: [PATCH] encapsulate `infcx` too into the delegate --- .../borrow_check/nll/type_check/relate_tys.rs | 118 +++++++++++++----- 1 file changed, 84 insertions(+), 34 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index f2934985f33e..39e340313636 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -31,8 +31,8 @@ pub(super) fn sub_types<'tcx>( ) -> Fallible<()> { debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations); TypeRelating::new( - infcx, - NllTypeRelatingDelegate::new(borrowck_context, locations, category), + infcx.tcx, + NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), ty::Variance::Covariant, ty::List::empty(), ).relate(&a, &b)?; @@ -50,8 +50,8 @@ pub(super) fn eq_types<'tcx>( ) -> Fallible<()> { debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations); TypeRelating::new( - infcx, - NllTypeRelatingDelegate::new(borrowck_context, locations, category), + infcx.tcx, + NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), ty::Variance::Invariant, ty::List::empty(), ).relate(&a, &b)?; @@ -85,8 +85,8 @@ pub(super) fn relate_type_and_user_type<'tcx>( let v1 = ty::Contravariant.xform(v); TypeRelating::new( - infcx, - NllTypeRelatingDelegate::new(borrowck_context, locations, category), + infcx.tcx, + NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), v1, b_variables, ).relate(&b_value, &a)?; @@ -97,7 +97,7 @@ struct TypeRelating<'me, 'gcx: 'tcx, 'tcx: 'me, D> where D: TypeRelatingDelegate<'tcx>, { - infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, + tcx: TyCtxt<'me, 'gcx, 'tcx>, /// Callback to use when we deduce an outlives relationship delegate: D, @@ -140,10 +140,37 @@ where } trait TypeRelatingDelegate<'tcx> { + /// Push a constraint `sup: sub` -- this constraint must be + /// satisfied for the two types to be related. `sub` and `sup` may + /// be regions from the type or new variables created through the + /// delegate. fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>); + + /// Creates a new region variable representing an instantiated + /// higher-ranked region; this will be either existential or + /// universal depending on the context. So e.g. if you have + /// `for<'a> fn(..) <: for<'b> fn(..)`, then we will first + /// instantiate `'b` with a universally quantitifed region and + /// then `'a` with an existentially quantified region (the order + /// is important so that the existential region `'a` can see the + /// universal one). + fn next_region_var( + &mut self, + universally_quantified: UniversallyQuantified, + ) -> ty::Region<'tcx>; + + /// Creates a new existential region in the given universe. This + /// is used when handling subtyping and type variables -- if we + /// have that `?X <: Foo<'a>`, for example, we would instantiate + /// `?X` with a type like `Foo<'?0>` where `'?0` is a fresh + /// existential variable created by this function. We would then + /// relate `Foo<'?0>` with `Foo<'a>` (and probably add an outlives + /// relation stating that `'?0: 'a`). + fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>; } -struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'tcx: 'bccx> { +struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'gcx: 'tcx, 'tcx: 'bccx> { + infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, /// Where (and why) is this relation taking place? @@ -153,13 +180,15 @@ struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'tcx: 'bccx> { category: ConstraintCategory, } -impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { +impl NllTypeRelatingDelegate<'me, 'bccx, 'gcx, 'tcx> { fn new( + infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, locations: Locations, category: ConstraintCategory, ) -> Self { Self { + infcx, borrowck_context, locations, category, @@ -167,7 +196,24 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } } -impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { +impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> { + fn next_region_var( + &mut self, + universally_quantified: UniversallyQuantified, + ) -> ty::Region<'tcx> { + let origin = if universally_quantified.0 { + NLLRegionVariableOrigin::BoundRegion(self.infcx.create_subuniverse()) + } else { + NLLRegionVariableOrigin::Existential + }; + self.infcx.next_nll_region_var(origin) + } + + fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { + self.infcx + .next_nll_region_var_in_universe(NLLRegionVariableOrigin::Existential, universe) + } + fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) { if let Some(borrowck_context) = &mut self.borrowck_context { let sub = borrowck_context.universal_regions.to_region_vid(sub); @@ -206,14 +252,14 @@ where D: TypeRelatingDelegate<'tcx>, { fn new( - infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, + tcx: TyCtxt<'me, 'gcx, 'tcx>, delegate: D, ambient_variance: ty::Variance, canonical_var_infos: CanonicalVarInfos<'tcx>, ) -> Self { let canonical_var_values = IndexVec::from_elem_n(None, canonical_var_infos.len()); Self { - infcx, + tcx, delegate, ambient_variance, canonical_var_values, @@ -243,7 +289,7 @@ where ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); value.skip_binder().visit_with(&mut ScopeInstantiator { - infcx: self.infcx, + delegate: &mut self.delegate, target_index: ty::INNERMOST, universally_quantified, bound_region_scope: &mut scope, @@ -335,9 +381,10 @@ where return result; } - fn generalize_value(&self, kind: Kind<'tcx>) -> Kind<'tcx> { + fn generalize_value(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { TypeGeneralizer { - type_rel: self, + tcx: self.tcx, + delegate: &mut self.delegate, first_free_index: ty::INNERMOST, ambient_variance: self.ambient_variance, @@ -354,7 +401,7 @@ where D: TypeRelatingDelegate<'tcx>, { fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> { - self.infcx.tcx + self.tcx } fn tag(&self) -> &'static str { @@ -559,15 +606,21 @@ where /// binder depth, and finds late-bound regions targeting the /// `for<..`>. For each of those, it creates an entry in /// `bound_region_scope`. -struct ScopeInstantiator<'me, 'gcx: 'tcx, 'tcx: 'me> { - infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, +struct ScopeInstantiator<'me, 'tcx: 'me, D> +where + D: TypeRelatingDelegate<'tcx> + 'me, +{ + delegate: &'me mut D, // The debruijn index of the scope we are instantiating. target_index: ty::DebruijnIndex, universally_quantified: UniversallyQuantified, bound_region_scope: &'me mut BoundRegionScope<'tcx>, } -impl<'me, 'gcx, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'gcx, 'tcx> { +impl<'me, 'tcx, D> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx, D> +where + D: TypeRelatingDelegate<'tcx>, +{ fn visit_binder>(&mut self, t: &ty::Binder) -> bool { self.target_index.shift_in(1); t.super_visit_with(self); @@ -578,21 +631,18 @@ impl<'me, 'gcx, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'gcx, 'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { let ScopeInstantiator { - infcx, universally_quantified, + bound_region_scope, + delegate, .. - } = *self; + } = self; match r { ty::ReLateBound(debruijn, br) if *debruijn == self.target_index => { - self.bound_region_scope.map.entry(*br).or_insert_with(|| { - let origin = if universally_quantified.0 { - NLLRegionVariableOrigin::BoundRegion(infcx.create_subuniverse()) - } else { - NLLRegionVariableOrigin::Existential - }; - infcx.next_nll_region_var(origin) - }); + bound_region_scope + .map + .entry(*br) + .or_insert_with(|| delegate.next_region_var(*universally_quantified)); } _ => {} @@ -625,7 +675,9 @@ struct TypeGeneralizer<'me, 'gcx: 'tcx, 'tcx: 'me, D> where D: TypeRelatingDelegate<'tcx> + 'me, { - type_rel: &'me TypeRelating<'me, 'gcx, 'tcx, D>, + tcx: TyCtxt<'me, 'gcx, 'tcx>, + + delegate: &'me mut D, /// After we generalize this type, we are going to relative it to /// some other type. What will be the variance at this point? @@ -641,7 +693,7 @@ where D: TypeRelatingDelegate<'tcx>, { fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> { - self.type_rel.infcx.tcx + self.tcx } fn tag(&self) -> &'static str { @@ -724,9 +776,7 @@ where // though, we may however need to check well-formedness or // risk a problem like #41677 again. - let replacement_region_vid = self.type_rel - .infcx - .next_nll_region_var_in_universe(NLLRegionVariableOrigin::Existential, self.universe); + let replacement_region_vid = self.delegate.generalize_existential(self.universe); Ok(replacement_region_vid) }