diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a5d7641504d..b13c9627bf7 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -28,7 +28,7 @@ use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace}; -use crate::infer::generalize::{Generalization, Generalizer}; +use crate::infer::generalize::{generalize, CombineDelegate, Generalization}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; @@ -471,25 +471,17 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { RelationDir::SupertypeOf => ty::Contravariant, }; - trace!(?ambient_variance); - - let for_universe = self.infcx.probe_ty_var(for_vid).unwrap_err(); - let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid); - - trace!(?for_universe); - trace!(?self.trace); - - Generalizer { - infcx: self.infcx, - delegate: self, + generalize::generalize( + self.infcx, + &mut CombineDelegate { + infcx: self.infcx, + param_env: self.param_env, + span: self.trace.span(), + }, + ty, + for_vid, ambient_variance, - for_universe, - for_vid_sub_root, - root_ty: ty, - cache: Default::default(), - needs_wf: false, - } - .generalize(ty) + ) } pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index 8913f5c8a43..c8562c84a17 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -4,12 +4,41 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::Span; -use crate::infer::combine::CombineFields; use crate::infer::nll_relate::TypeRelatingDelegate; use crate::infer::type_variable::TypeVariableValue; use crate::infer::{InferCtxt, RegionVariableOrigin}; +pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>>( + infcx: &InferCtxt<'tcx>, + delegate: &mut D, + ty: Ty<'tcx>, + for_vid: ty::TyVid, + ambient_variance: ty::Variance, +) -> RelateResult<'tcx, Generalization>> { + let for_universe = infcx.probe_ty_var(for_vid).unwrap_err(); + let for_vid_sub_root = infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid); + + let mut generalizer = Generalizer { + infcx, + delegate, + ambient_variance, + for_vid_sub_root, + for_universe, + root_ty: ty, + needs_wf: false, + cache: Default::default(), + }; + + assert!(!ty.has_escaping_bound_vars()); + let value = generalizer.relate(ty, ty)?; + let needs_wf = generalizer.needs_wf; + Ok(Generalization { value, needs_wf }) +} + +/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking +/// in the generalizer code. pub trait GeneralizerDelegate<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx>; @@ -18,7 +47,13 @@ pub trait GeneralizerDelegate<'tcx> { fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>; } -impl<'tcx> GeneralizerDelegate<'tcx> for CombineFields<'_, 'tcx> { +pub struct CombineDelegate<'cx, 'tcx> { + pub infcx: &'cx InferCtxt<'tcx>, + pub param_env: ty::ParamEnv<'tcx>, + pub span: Span, +} + +impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } @@ -28,10 +63,8 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineFields<'_, 'tcx> { } fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - self.infcx.next_region_var_in_universe( - RegionVariableOrigin::MiscVariable(self.trace.span()), - universe, - ) + self.infcx + .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe) } } @@ -66,7 +99,7 @@ where /// establishes `'0: 'x` as a constraint. /// /// [blog post]: https://is.gd/0hKvIr -pub(super) struct Generalizer<'me, 'tcx, D> +struct Generalizer<'me, 'tcx, D> where D: GeneralizerDelegate<'tcx>, { @@ -98,18 +131,6 @@ where needs_wf: bool, } -impl<'tcx, D: GeneralizerDelegate<'tcx>> Generalizer<'_, 'tcx, D> { - pub fn generalize(mut self, value: T) -> RelateResult<'tcx, Generalization> - where - T: Relate<'tcx>, - { - assert!(!value.has_escaping_bound_vars()); - let value = self.relate(value, value)?; - let needs_wf = self.needs_wf; - Ok(Generalization { value, needs_wf }) - } -} - impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D> where D: GeneralizerDelegate<'tcx>, @@ -202,17 +223,19 @@ where } ty::Infer(ty::TyVar(vid)) => { - let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid); - let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid); + let mut inner = self.infcx.inner.borrow_mut(); + let vid = inner.type_variables().root_var(vid); + let sub_vid = inner.type_variables().sub_root_var(vid); if sub_vid == self.for_vid_sub_root { // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. Err(TypeError::CyclicTy(self.root_ty)) } else { - let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid); + let probe = inner.type_variables().probe(vid); match probe { TypeVariableValue::Known { value: u } => { debug!("generalize: known value {:?}", u); + drop(inner); self.relate(u, u) } TypeVariableValue::Unknown { universe } => { @@ -235,20 +258,15 @@ where ty::Covariant | ty::Contravariant => (), } - let origin = - *self.infcx.inner.borrow_mut().type_variables().var_origin(vid); - let new_var_id = self - .infcx - .inner - .borrow_mut() - .type_variables() - .new_var(self.for_universe, origin); + let origin = *inner.type_variables().var_origin(vid); + let new_var_id = + inner.type_variables().new_var(self.for_universe, origin); let u = self.tcx().mk_ty_var(new_var_id); // Record that we replaced `vid` with `new_var_id` as part of a generalization // operation. This is needed to detect cyclic types. To see why, see the // docs in the `type_variables` module. - self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id); + inner.type_variables().sub(vid, new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); Ok(u) } @@ -278,7 +296,7 @@ where ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { let s = self.relate(substs, substs)?; - Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) }) + Ok(if s == substs { t } else { self.tcx().mk_opaque(def_id, s) }) } _ => relate::super_relate_tys(self, t, t), }?; diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index f479dbdc43c..4ae6af5f5be 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -31,7 +31,7 @@ use rustc_span::{Span, Symbol}; use std::fmt::Debug; use crate::infer::combine::ObligationEmittingRelation; -use crate::infer::generalize::{Generalization, Generalizer}; +use crate::infer::generalize::{self, Generalization}; use crate::infer::InferCtxt; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::{Obligation, PredicateObligations}; @@ -217,23 +217,14 @@ where } fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> { - let for_universe = self.infcx.probe_ty_var(for_vid).unwrap_err(); - let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid); - - // FIXME: we may need a WF predicate (related to #54105). - let Generalization { value, needs_wf: _ } = Generalizer { - infcx: self.infcx, - delegate: &mut self.delegate, - ambient_variance: self.ambient_variance, - for_vid_sub_root, - for_universe, - root_ty: ty, - needs_wf: false, - cache: Default::default(), - } - .generalize(ty)?; - - Ok(value) + let Generalization { value: ty, needs_wf: _ } = generalize::generalize( + self.infcx, + &mut self.delegate, + ty, + for_vid, + self.ambient_variance, + )?; + Ok(ty) } fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {