Restrict const ty's regions to static when putting them in canonical var list
This commit is contained in:
parent
4ea92e3c7a
commit
08c7ff2264
@ -140,6 +140,10 @@ impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
|
||||
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
|
||||
Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
|
||||
}
|
||||
|
||||
fn new_static(tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.lifetimes.re_static
|
||||
}
|
||||
}
|
||||
|
||||
/// Region utilities
|
||||
|
@ -382,43 +382,47 @@ fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
// We could canonicalize all consts with static types, but the only ones we
|
||||
// *really* need to worry about are the ones that we end up putting into `CanonicalVarKind`
|
||||
// since canonical vars can't reference other canonical vars.
|
||||
let ty = c
|
||||
.ty()
|
||||
.fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST });
|
||||
let kind = match c.kind() {
|
||||
ty::ConstKind::Infer(i) => {
|
||||
// FIXME: we should fold the ty too eventually
|
||||
match i {
|
||||
ty::InferConst::Var(vid) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_ct_var(vid),
|
||||
vid,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
assert_eq!(
|
||||
self.infcx.probe_ct_var(vid),
|
||||
None,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
|
||||
}
|
||||
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
|
||||
ty::InferConst::Fresh(_) => todo!(),
|
||||
ty::ConstKind::Infer(i) => match i {
|
||||
ty::InferConst::Var(vid) => {
|
||||
assert_eq!(
|
||||
self.infcx.root_ct_var(vid),
|
||||
vid,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
assert_eq!(
|
||||
self.infcx.probe_ct_var(vid),
|
||||
None,
|
||||
"region vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
|
||||
}
|
||||
}
|
||||
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
|
||||
ty::InferConst::Fresh(_) => todo!(),
|
||||
},
|
||||
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
|
||||
c.ty(),
|
||||
ty,
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty)
|
||||
}
|
||||
},
|
||||
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||
c.ty(),
|
||||
ty,
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
||||
},
|
||||
// FIXME: See comment above -- we could fold the region separately or something.
|
||||
ty::ConstKind::Bound(_, _)
|
||||
| ty::ConstKind::Unevaluated(_)
|
||||
| ty::ConstKind::Value(_)
|
||||
@ -435,6 +439,35 @@ fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||
}),
|
||||
);
|
||||
|
||||
Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty())
|
||||
Const::new_anon_bound(self.interner(), self.binder_index, var, ty)
|
||||
}
|
||||
}
|
||||
|
||||
struct RegionsToStatic<I> {
|
||||
interner: I,
|
||||
binder: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
|
||||
fn interner(&self) -> I {
|
||||
self.interner
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
self.binder.shift_in(1);
|
||||
let t = t.fold_with(self);
|
||||
self.binder.shift_out(1);
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: I::Region) -> I::Region {
|
||||
match r.kind() {
|
||||
ty::ReBound(db, _) if self.binder > db => r,
|
||||
_ => Region::new_static(self.interner()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,14 @@
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::fold::TypeSuperFoldable;
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||
use crate::{
|
||||
new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
|
||||
UniverseIndex,
|
||||
};
|
||||
|
||||
pub trait Interner: Sized {
|
||||
pub trait Interner: Sized + Copy {
|
||||
type DefId: Copy + Debug + Hash + Eq;
|
||||
type AdtDef: Copy + Debug + Hash + Eq;
|
||||
|
||||
@ -34,6 +35,7 @@ pub trait Interner: Sized {
|
||||
+ Into<Self::GenericArg>
|
||||
+ IntoKind<Kind = TyKind<Self>>
|
||||
+ TypeSuperVisitable<Self>
|
||||
+ TypeSuperFoldable<Self>
|
||||
+ Flags
|
||||
+ new::Ty<Self>;
|
||||
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
|
||||
@ -57,6 +59,7 @@ pub trait Interner: Sized {
|
||||
+ IntoKind<Kind = ConstKind<Self>>
|
||||
+ ConstTy<Self>
|
||||
+ TypeSuperVisitable<Self>
|
||||
+ TypeSuperFoldable<Self>
|
||||
+ Flags
|
||||
+ new::Const<Self>;
|
||||
type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
||||
|
@ -6,6 +6,8 @@ pub trait Ty<I: Interner<Ty = Self>> {
|
||||
|
||||
pub trait Region<I: Interner<Region = Self>> {
|
||||
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
|
||||
|
||||
fn new_static(interner: I) -> Self;
|
||||
}
|
||||
|
||||
pub trait Const<I: Interner<Const = Self>> {
|
||||
|
@ -0,0 +1,23 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(adt_const_params)]
|
||||
//~^ WARN the feature `adt_const_params` is incomplete
|
||||
#![feature(with_negative_coherence, negative_impls)]
|
||||
|
||||
pub trait A<const K: &'static str> {}
|
||||
pub trait C {}
|
||||
|
||||
|
||||
struct W<T>(T);
|
||||
|
||||
// Negative coherence:
|
||||
// Proving `W<!T>: !A<"">` requires proving `CONST alias-eq ""`, which requires proving
|
||||
// `CONST normalizes-to (?1c: &str)`. The type's region is uniquified, so it ends up being
|
||||
// put in to the canonical vars list with an infer region => ICE.
|
||||
impl<T> C for T where T: A<""> {}
|
||||
impl<T> C for W<T> {}
|
||||
|
||||
impl<T> !A<CONST> for W<T> {}
|
||||
const CONST: &str = "";
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/regions-in-canonical.rs:3:12
|
||||
|
|
||||
LL | #![feature(adt_const_params)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user