Implement fallback for effect param
This commit is contained in:
parent
b14b0745ad
commit
84a490712a
20 changed files with 390 additions and 72 deletions
|
@ -173,6 +173,7 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
|
|||
CanonicalVarKind::PlaceholderRegion(..) => false,
|
||||
CanonicalVarKind::Const(..) => true,
|
||||
CanonicalVarKind::PlaceholderConst(_, _) => false,
|
||||
CanonicalVarKind::Effect => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +183,8 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
|
|||
CanonicalVarKind::Ty(_)
|
||||
| CanonicalVarKind::PlaceholderTy(_)
|
||||
| CanonicalVarKind::Const(_, _)
|
||||
| CanonicalVarKind::PlaceholderConst(_, _) => false,
|
||||
| CanonicalVarKind::PlaceholderConst(_, _)
|
||||
| CanonicalVarKind::Effect => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +192,8 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
|
|||
match self.kind {
|
||||
CanonicalVarKind::Ty(_)
|
||||
| CanonicalVarKind::Region(_)
|
||||
| CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
|
||||
| CanonicalVarKind::Const(_, _)
|
||||
| CanonicalVarKind::Effect => bug!("expected placeholder: {self:?}"),
|
||||
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
|
||||
|
@ -222,6 +225,9 @@ pub enum CanonicalVarKind<'tcx> {
|
|||
/// Some kind of const inference variable.
|
||||
Const(ty::UniverseIndex, Ty<'tcx>),
|
||||
|
||||
/// Effect variable `'?E`.
|
||||
Effect,
|
||||
|
||||
/// A "placeholder" that represents "any const".
|
||||
PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>),
|
||||
}
|
||||
|
@ -229,11 +235,11 @@ pub enum CanonicalVarKind<'tcx> {
|
|||
impl<'tcx> CanonicalVarKind<'tcx> {
|
||||
pub fn universe(self) -> ty::UniverseIndex {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(kind) => match kind {
|
||||
CanonicalTyVarKind::General(ui) => ui,
|
||||
CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
|
||||
},
|
||||
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
|
||||
ty::UniverseIndex::ROOT
|
||||
}
|
||||
CanonicalVarKind::Effect => ty::UniverseIndex::ROOT,
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
|
||||
CanonicalVarKind::Region(ui) => ui,
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
|
||||
|
@ -248,15 +254,14 @@ impl<'tcx> CanonicalVarKind<'tcx> {
|
|||
/// the updated universe is not the root.
|
||||
pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(kind) => match kind {
|
||||
CanonicalTyVarKind::General(_) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||
}
|
||||
CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
|
||||
assert_eq!(ui, ty::UniverseIndex::ROOT);
|
||||
CanonicalVarKind::Ty(kind)
|
||||
}
|
||||
},
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||
}
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
||||
| CanonicalVarKind::Effect => {
|
||||
assert_eq!(ui, ty::UniverseIndex::ROOT);
|
||||
self
|
||||
}
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
|
||||
}
|
||||
|
@ -443,6 +448,14 @@ impl<'tcx> CanonicalVarValues<'tcx> {
|
|||
};
|
||||
ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
|
||||
}
|
||||
// todo eh?
|
||||
CanonicalVarKind::Effect => ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(i),
|
||||
tcx.types.bool,
|
||||
)
|
||||
.into(),
|
||||
CanonicalVarKind::Const(_, ty)
|
||||
| CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound(
|
||||
tcx,
|
||||
|
|
|
@ -188,3 +188,53 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// values for the effect inference variable
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum EffectVarValue<'tcx> {
|
||||
/// The host effect is on, enabling access to syscalls, filesystem access, etc.
|
||||
Host,
|
||||
/// The host effect is off. Execution is restricted to const operations only.
|
||||
NoHost,
|
||||
Const(ty::Const<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> EffectVarValue<'tcx> {
|
||||
pub fn as_const(self, tcx: TyCtxt<'tcx>) -> ty::Const<'tcx> {
|
||||
match self {
|
||||
EffectVarValue::Host => tcx.consts.true_,
|
||||
EffectVarValue::NoHost => tcx.consts.false_,
|
||||
EffectVarValue::Const(c) => c,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnifyValue for EffectVarValue<'tcx> {
|
||||
type Error = (EffectVarValue<'tcx>, EffectVarValue<'tcx>);
|
||||
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
|
||||
match (value1, value2) {
|
||||
(EffectVarValue::Host, EffectVarValue::Host) => Ok(EffectVarValue::Host),
|
||||
(EffectVarValue::NoHost, EffectVarValue::NoHost) => Ok(EffectVarValue::NoHost),
|
||||
(EffectVarValue::NoHost | EffectVarValue::Host, _)
|
||||
| (_, EffectVarValue::NoHost | EffectVarValue::Host) => Err((*value1, *value2)),
|
||||
(EffectVarValue::Const(_), EffectVarValue::Const(_)) => {
|
||||
bug!("equating two const variables, both of which have known values")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnifyKey for ty::EffectVid<'tcx> {
|
||||
type Value = Option<EffectVarValue<'tcx>>;
|
||||
#[inline]
|
||||
fn index(&self) -> u32 {
|
||||
self.index
|
||||
}
|
||||
#[inline]
|
||||
fn from_index(i: u32) -> Self {
|
||||
ty::EffectVid { index: i, phantom: PhantomData }
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"EffectVid"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ static_assert_size!(super::ConstKind<'_>, 32);
|
|||
pub enum InferConst<'tcx> {
|
||||
/// Infer the value of the const.
|
||||
Var(ty::ConstVid<'tcx>),
|
||||
/// Infer the value of the effect.
|
||||
///
|
||||
/// For why this is separate from the `Var` variant above, see the
|
||||
/// documentation on `EffectVid`.
|
||||
EffectVar(ty::EffectVid<'tcx>),
|
||||
/// A fresh const variable. See `infer::freshen` for more details.
|
||||
Fresh(u32),
|
||||
}
|
||||
|
@ -62,7 +67,9 @@ pub enum InferConst<'tcx> {
|
|||
impl<CTX> HashStable<CTX> for InferConst<'_> {
|
||||
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
|
||||
match self {
|
||||
InferConst::Var(_) => panic!("const variables should not be hashed: {self:?}"),
|
||||
InferConst::Var(_) | InferConst::EffectVar(_) => {
|
||||
panic!("const variables should not be hashed: {self:?}")
|
||||
}
|
||||
InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,7 +324,9 @@ impl FlagComputation {
|
|||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
match infer {
|
||||
InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
|
||||
InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
|
||||
InferConst::Var(_) | InferConst::EffectVar(_) => {
|
||||
self.add_flags(TypeFlags::HAS_CT_INFER)
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Bound(debruijn, _) => {
|
||||
|
|
|
@ -98,9 +98,9 @@ pub use self::sty::BoundRegionKind::*;
|
|||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
|
||||
BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid,
|
||||
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
|
||||
FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, InlineConstArgsParts,
|
||||
ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
|
||||
EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef,
|
||||
FnSig, FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs,
|
||||
InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
|
||||
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid,
|
||||
TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
|
||||
};
|
||||
|
|
|
@ -138,6 +138,12 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::EffectVid<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "?{}e", self.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
|
||||
|
@ -253,6 +259,7 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
InferConst::Var(var) => write!(f, "{var:?}"),
|
||||
InferConst::EffectVar(var) => write!(f, "{var:?}"),
|
||||
InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +274,7 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst<'tcx> {
|
|||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => match *this.data {
|
||||
Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()),
|
||||
EffectVar(vid) => write!(f, "?{}_{}e", vid.index, universe.index()),
|
||||
Fresh(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -1577,6 +1577,20 @@ pub struct ConstVid<'tcx> {
|
|||
pub phantom: PhantomData<&'tcx ()>,
|
||||
}
|
||||
|
||||
/// An **effect** **v**ariable **ID**.
|
||||
///
|
||||
/// Handling effect infer variables happens separately from const infer variables
|
||||
/// because we do not want to reuse any of the const infer machinery. If we try to
|
||||
/// relate an effect variable with a normal one, we would ICE, which can catch bugs
|
||||
/// where we are not correctly using the effect var for an effect param. Fallback
|
||||
/// is also implemented on top of having separate effect and normal const variables.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
pub struct EffectVid<'tcx> {
|
||||
pub index: u32,
|
||||
pub phantom: PhantomData<&'tcx ()>,
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A **region** (lifetime) **v**ariable **ID**.
|
||||
#[derive(HashStable)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue