Rollup merge of #123170 - compiler-errors:const-statics, r=lcnr
Replace regions in const canonical vars' types with `'static` in next-solver canonicalizer We shouldn't ever have non-static regions in consts on stable (or really any regions at all, lol). The test I committed is less minimal than, e.g., https://github.com/rust-lang/rust/issues/123155?notification_referrer_id=NT_kwDOADgQyrMxMDAzNDU4MDI0OTozNjc0MzE0#issuecomment-2025472029 -- however, I believe that it actually portrays the underlying issue here a bit better than that one. In the linked issue, we end up emitting a normalizes-to predicate for a const placeholder because we don't actually unify `false` and `""`. In the test I committed, we emit a normalizes-to predicate as a part of actually solving a negative coherence goal. Fixes #123155 Fixes #118783 r? lcnr
This commit is contained in:
commit
93f1443280
7 changed files with 120 additions and 73 deletions
|
@ -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
|
||||
|
|
|
@ -296,10 +296,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
Region::new_anon_bound(self.interner(), self.binder_index, var)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: I::Ty) -> I::Ty
|
||||
where
|
||||
I::Ty: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
|
||||
let kind = match t.kind() {
|
||||
ty::Infer(i) => match i {
|
||||
ty::TyVar(vid) => {
|
||||
|
@ -378,47 +375,48 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
Ty::new_anon_bound(self.interner(), self.binder_index, var)
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn fold_const(&mut self, c: I::Const) -> I::Const {
|
||||
// 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 +433,35 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
}),
|
||||
);
|
||||
|
||||
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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,31 +136,21 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
|
|||
t.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: I::Ty) -> I::Ty
|
||||
where
|
||||
I::Ty: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
|
||||
// The default region folder is a no-op because `Region` is non-recursive
|
||||
// and has no `super_fold_with` method to call. That also explains the
|
||||
// lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
|
||||
// and has no `super_fold_with` method to call.
|
||||
fn fold_region(&mut self, r: I::Region) -> I::Region {
|
||||
r
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn fold_const(&mut self, c: I::Const) -> I::Const {
|
||||
c.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate
|
||||
where
|
||||
I::Predicate: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
|
||||
p.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
@ -185,31 +175,21 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
|
|||
t.try_super_fold_with(self)
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error>
|
||||
where
|
||||
I::Ty: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> {
|
||||
t.try_super_fold_with(self)
|
||||
}
|
||||
|
||||
// The default region folder is a no-op because `Region` is non-recursive
|
||||
// and has no `super_fold_with` method to call. That also explains the
|
||||
// lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
|
||||
// and has no `super_fold_with` method to call.
|
||||
fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error> {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error>
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> {
|
||||
c.try_super_fold_with(self)
|
||||
}
|
||||
|
||||
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error>
|
||||
where
|
||||
I::Predicate: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> {
|
||||
p.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
@ -234,10 +214,7 @@ where
|
|||
Ok(self.fold_binder(t))
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never>
|
||||
where
|
||||
I::Ty: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never> {
|
||||
Ok(self.fold_ty(t))
|
||||
}
|
||||
|
||||
|
@ -245,17 +222,11 @@ where
|
|||
Ok(self.fold_region(r))
|
||||
}
|
||||
|
||||
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never>
|
||||
where
|
||||
I::Const: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never> {
|
||||
Ok(self.fold_const(c))
|
||||
}
|
||||
|
||||
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never>
|
||||
where
|
||||
I::Predicate: TypeSuperFoldable<I>,
|
||||
{
|
||||
fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never> {
|
||||
Ok(self.fold_predicate(p))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ use smallvec::SmallVec;
|
|||
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;
|
||||
|
@ -82,7 +85,13 @@ pub trait Interner: Sized {
|
|||
type PlaceholderRegion: Copy + Debug + Hash + Eq + PlaceholderLike;
|
||||
|
||||
// Predicates
|
||||
type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
|
||||
type Predicate: Copy
|
||||
+ Debug
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ TypeSuperVisitable<Self>
|
||||
+ TypeSuperFoldable<Self>
|
||||
+ Flags;
|
||||
type TraitPredicate: Copy + Debug + Hash + Eq;
|
||||
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
|
||||
type TypeOutlivesPredicate: Copy + Debug + 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>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue