Replace RelationDir with Variance
This commit is contained in:
parent
41501c7449
commit
a2678e15e5
@ -48,13 +48,6 @@ pub struct CombineFields<'infcx, 'tcx> {
|
||||
pub define_opaque_types: DefineOpaqueTypes,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RelationDir {
|
||||
SubtypeOf,
|
||||
SupertypeOf,
|
||||
EqTo,
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn super_combine_tys<R>(
|
||||
&self,
|
||||
@ -378,12 +371,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
pub fn instantiate(
|
||||
&mut self,
|
||||
a_ty: Ty<'tcx>,
|
||||
dir: RelationDir,
|
||||
ambient_variance: ty::Variance,
|
||||
b_vid: ty::TyVid,
|
||||
a_is_expected: bool,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
use self::RelationDir::*;
|
||||
|
||||
// Get the actual variable that b_vid has been inferred to
|
||||
debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
|
||||
|
||||
@ -398,7 +389,18 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
// `'?2` and `?3` are fresh region/type inference
|
||||
// variables. (Down below, we will relate `a_ty <: b_ty`,
|
||||
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
|
||||
let Generalization { value: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
|
||||
let Generalization { value: b_ty, needs_wf } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut CombineDelegate {
|
||||
infcx: self.infcx,
|
||||
param_env: self.param_env,
|
||||
span: self.trace.span(),
|
||||
},
|
||||
a_ty,
|
||||
b_vid,
|
||||
ambient_variance,
|
||||
)?;
|
||||
|
||||
debug!(?b_ty);
|
||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||
|
||||
@ -417,62 +419,23 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
||||
// relations wind up attributed to the same spans. We need
|
||||
// to associate causes/spans with each of the relations in
|
||||
// the stack to get this right.
|
||||
match dir {
|
||||
EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
SupertypeOf => self.sub(a_is_expected).relate_with_variance(
|
||||
match ambient_variance {
|
||||
ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
|
||||
ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
|
||||
ty::Contravariant,
|
||||
ty::VarianceDiagInfo::default(),
|
||||
a_ty,
|
||||
b_ty,
|
||||
),
|
||||
ty::Variance::Bivariant => {
|
||||
unreachable!("no code should be generalizing bivariantly (currently)")
|
||||
}
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempts to generalize `ty` for the type variable `for_vid`.
|
||||
/// This checks for cycle -- that is, whether the type `ty`
|
||||
/// references `for_vid`. The `dir` is the "direction" for which we
|
||||
/// a performing the generalization (i.e., are we producing a type
|
||||
/// that can be used as a supertype etc).
|
||||
///
|
||||
/// Preconditions:
|
||||
///
|
||||
/// - `for_vid` is a "root vid"
|
||||
#[instrument(skip(self), level = "trace", ret)]
|
||||
fn generalize(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
for_vid: ty::TyVid,
|
||||
dir: RelationDir,
|
||||
) -> RelateResult<'tcx, Generalization<Ty<'tcx>>> {
|
||||
// Determine the ambient variance within which `ty` appears.
|
||||
// The surrounding equation is:
|
||||
//
|
||||
// ty [op] ty2
|
||||
//
|
||||
// where `op` is either `==`, `<:`, or `:>`. This maps quite
|
||||
// naturally.
|
||||
let ambient_variance = match dir {
|
||||
RelationDir::EqTo => ty::Invariant,
|
||||
RelationDir::SubtypeOf => ty::Covariant,
|
||||
RelationDir::SupertypeOf => ty::Contravariant,
|
||||
};
|
||||
|
||||
generalize::generalize(
|
||||
self.infcx,
|
||||
&mut CombineDelegate {
|
||||
infcx: self.infcx,
|
||||
param_env: self.param_env,
|
||||
span: self.trace.span(),
|
||||
},
|
||||
ty,
|
||||
for_vid,
|
||||
ambient_variance,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
|
||||
self.obligations.extend(obligations.into_iter());
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::infer::DefineOpaqueTypes;
|
||||
use crate::traits::PredicateObligations;
|
||||
|
||||
use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
|
||||
use super::combine::{CombineFields, ObligationEmittingRelation};
|
||||
use super::Subtype;
|
||||
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
@ -88,11 +88,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
||||
}
|
||||
|
||||
(&ty::Infer(TyVar(a_id)), _) => {
|
||||
self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?;
|
||||
}
|
||||
|
||||
(_, &ty::Infer(TyVar(b_id))) => {
|
||||
self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?;
|
||||
}
|
||||
|
||||
(
|
||||
|
@ -10,6 +10,9 @@ use crate::infer::nll_relate::TypeRelatingDelegate;
|
||||
use crate::infer::type_variable::TypeVariableValue;
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin};
|
||||
|
||||
/// Attempts to generalize `term` for the type variable `for_vid`.
|
||||
/// This checks for cycles -- that is, whether the type `term`
|
||||
/// references `for_vid`.
|
||||
pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
delegate: &mut D,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::combine::{CombineFields, RelationDir};
|
||||
use super::combine::CombineFields;
|
||||
use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
|
||||
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
@ -108,11 +108,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
||||
Ok(a)
|
||||
}
|
||||
(&ty::Infer(TyVar(a_id)), _) => {
|
||||
self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
|
||||
self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?;
|
||||
Ok(a)
|
||||
}
|
||||
(_, &ty::Infer(TyVar(b_id))) => {
|
||||
self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
|
||||
self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?;
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user