1
Fork 0

Simplify delegate

This commit is contained in:
Michael Goulet 2023-05-04 20:40:02 +00:00
parent 338e7642fb
commit c270b0a8a8
3 changed files with 70 additions and 69 deletions

View file

@ -28,7 +28,7 @@ use super::lub::Lub;
use super::sub::Sub; use super::sub::Sub;
use super::type_variable::TypeVariableValue; use super::type_variable::TypeVariableValue;
use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace}; 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 crate::traits::{Obligation, PredicateObligations};
use rustc_middle::infer::canonical::OriginalQueryValues; use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
@ -471,25 +471,17 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
RelationDir::SupertypeOf => ty::Contravariant, RelationDir::SupertypeOf => ty::Contravariant,
}; };
trace!(?ambient_variance); generalize::generalize(
self.infcx,
let for_universe = self.infcx.probe_ty_var(for_vid).unwrap_err(); &mut CombineDelegate {
let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid); infcx: self.infcx,
param_env: self.param_env,
trace!(?for_universe); span: self.trace.span(),
trace!(?self.trace); },
ty,
Generalizer { for_vid,
infcx: self.infcx,
delegate: self,
ambient_variance, 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>) { pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {

View file

@ -4,12 +4,41 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt}; 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::nll_relate::TypeRelatingDelegate;
use crate::infer::type_variable::TypeVariableValue; use crate::infer::type_variable::TypeVariableValue;
use crate::infer::{InferCtxt, RegionVariableOrigin}; 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<Ty<'tcx>>> {
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> { pub trait GeneralizerDelegate<'tcx> {
fn param_env(&self) -> ty::ParamEnv<'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>; 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> { fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env 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> { fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
self.infcx.next_region_var_in_universe( self.infcx
RegionVariableOrigin::MiscVariable(self.trace.span()), .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
universe,
)
} }
} }
@ -66,7 +99,7 @@ where
/// establishes `'0: 'x` as a constraint. /// establishes `'0: 'x` as a constraint.
/// ///
/// [blog post]: https://is.gd/0hKvIr /// [blog post]: https://is.gd/0hKvIr
pub(super) struct Generalizer<'me, 'tcx, D> struct Generalizer<'me, 'tcx, D>
where where
D: GeneralizerDelegate<'tcx>, D: GeneralizerDelegate<'tcx>,
{ {
@ -98,18 +131,6 @@ where
needs_wf: bool, needs_wf: bool,
} }
impl<'tcx, D: GeneralizerDelegate<'tcx>> Generalizer<'_, 'tcx, D> {
pub fn generalize<T>(mut self, value: T) -> RelateResult<'tcx, Generalization<T>>
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> impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
where where
D: GeneralizerDelegate<'tcx>, D: GeneralizerDelegate<'tcx>,
@ -202,17 +223,19 @@ where
} }
ty::Infer(ty::TyVar(vid)) => { ty::Infer(ty::TyVar(vid)) => {
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid); let mut inner = self.infcx.inner.borrow_mut();
let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid); 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_vid == self.for_vid_sub_root {
// If sub-roots are equal, then `for_vid` and // If sub-roots are equal, then `for_vid` and
// `vid` are related via subtyping. // `vid` are related via subtyping.
Err(TypeError::CyclicTy(self.root_ty)) Err(TypeError::CyclicTy(self.root_ty))
} else { } else {
let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid); let probe = inner.type_variables().probe(vid);
match probe { match probe {
TypeVariableValue::Known { value: u } => { TypeVariableValue::Known { value: u } => {
debug!("generalize: known value {:?}", u); debug!("generalize: known value {:?}", u);
drop(inner);
self.relate(u, u) self.relate(u, u)
} }
TypeVariableValue::Unknown { universe } => { TypeVariableValue::Unknown { universe } => {
@ -235,20 +258,15 @@ where
ty::Covariant | ty::Contravariant => (), ty::Covariant | ty::Contravariant => (),
} }
let origin = let origin = *inner.type_variables().var_origin(vid);
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid); let new_var_id =
let new_var_id = self inner.type_variables().new_var(self.for_universe, origin);
.infcx
.inner
.borrow_mut()
.type_variables()
.new_var(self.for_universe, origin);
let u = self.tcx().mk_ty_var(new_var_id); let u = self.tcx().mk_ty_var(new_var_id);
// Record that we replaced `vid` with `new_var_id` as part of a generalization // 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 // operation. This is needed to detect cyclic types. To see why, see the
// docs in the `type_variables` module. // 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); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
Ok(u) Ok(u)
} }
@ -278,7 +296,7 @@ where
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
let s = self.relate(substs, 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), _ => relate::super_relate_tys(self, t, t),
}?; }?;

View file

@ -31,7 +31,7 @@ use rustc_span::{Span, Symbol};
use std::fmt::Debug; use std::fmt::Debug;
use crate::infer::combine::ObligationEmittingRelation; use crate::infer::combine::ObligationEmittingRelation;
use crate::infer::generalize::{Generalization, Generalizer}; use crate::infer::generalize::{self, Generalization};
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::{Obligation, PredicateObligations}; 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>> { 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 Generalization { value: ty, needs_wf: _ } = generalize::generalize(
let for_vid_sub_root = self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid); self.infcx,
&mut self.delegate,
// FIXME: we may need a WF predicate (related to #54105). ty,
let Generalization { value, needs_wf: _ } = Generalizer { for_vid,
infcx: self.infcx, self.ambient_variance,
delegate: &mut self.delegate, )?;
ambient_variance: self.ambient_variance, Ok(ty)
for_vid_sub_root,
for_universe,
root_ty: ty,
needs_wf: false,
cache: Default::default(),
}
.generalize(ty)?;
Ok(value)
} }
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {