Skip to content

Commit 08c7ff2

Browse files
Restrict const ty's regions to static when putting them in canonical var list
1 parent 4ea92e3 commit 08c7ff2

File tree

6 files changed

+100
-24
lines changed

6 files changed

+100
-24
lines changed

compiler/rustc_middle/src/ty/region.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
140140
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
141141
Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
142142
}
143+
144+
fn new_static(tcx: TyCtxt<'tcx>) -> Self {
145+
tcx.lifetimes.re_static
146+
}
143147
}
144148

145149
/// Region utilities

compiler/rustc_next_trait_solver/src/canonicalizer.rs

+56-23
Original file line numberDiff line numberDiff line change
@@ -382,43 +382,47 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
382382
where
383383
I::Const: TypeSuperFoldable<I>,
384384
{
385+
// We could canonicalize all consts with static types, but the only ones we
386+
// *really* need to worry about are the ones that we end up putting into `CanonicalVarKind`
387+
// since canonical vars can't reference other canonical vars.
388+
let ty = c
389+
.ty()
390+
.fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST });
385391
let kind = match c.kind() {
386-
ty::ConstKind::Infer(i) => {
387-
// FIXME: we should fold the ty too eventually
388-
match i {
389-
ty::InferConst::Var(vid) => {
390-
assert_eq!(
391-
self.infcx.root_ct_var(vid),
392-
vid,
393-
"region vid should have been resolved fully before canonicalization"
394-
);
395-
assert_eq!(
396-
self.infcx.probe_ct_var(vid),
397-
None,
398-
"region vid should have been resolved fully before canonicalization"
399-
);
400-
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
401-
}
402-
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
403-
ty::InferConst::Fresh(_) => todo!(),
392+
ty::ConstKind::Infer(i) => match i {
393+
ty::InferConst::Var(vid) => {
394+
assert_eq!(
395+
self.infcx.root_ct_var(vid),
396+
vid,
397+
"region vid should have been resolved fully before canonicalization"
398+
);
399+
assert_eq!(
400+
self.infcx.probe_ct_var(vid),
401+
None,
402+
"region vid should have been resolved fully before canonicalization"
403+
);
404+
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
404405
}
405-
}
406+
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
407+
ty::InferConst::Fresh(_) => todo!(),
408+
},
406409
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
407410
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
408411
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
409-
c.ty(),
412+
ty,
410413
),
411414
CanonicalizeMode::Response { .. } => {
412-
CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
415+
CanonicalVarKind::PlaceholderConst(placeholder, ty)
413416
}
414417
},
415418
ty::ConstKind::Param(_) => match self.canonicalize_mode {
416419
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
417420
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
418-
c.ty(),
421+
ty,
419422
),
420423
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
421424
},
425+
// FIXME: See comment above -- we could fold the region separately or something.
422426
ty::ConstKind::Bound(_, _)
423427
| ty::ConstKind::Unevaluated(_)
424428
| ty::ConstKind::Value(_)
@@ -435,6 +439,35 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
435439
}),
436440
);
437441

438-
Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty())
442+
Const::new_anon_bound(self.interner(), self.binder_index, var, ty)
443+
}
444+
}
445+
446+
struct RegionsToStatic<I> {
447+
interner: I,
448+
binder: ty::DebruijnIndex,
449+
}
450+
451+
impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
452+
fn interner(&self) -> I {
453+
self.interner
454+
}
455+
456+
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
457+
where
458+
T: TypeFoldable<I>,
459+
I::Binder<T>: TypeSuperFoldable<I>,
460+
{
461+
self.binder.shift_in(1);
462+
let t = t.fold_with(self);
463+
self.binder.shift_out(1);
464+
t
465+
}
466+
467+
fn fold_region(&mut self, r: I::Region) -> I::Region {
468+
match r.kind() {
469+
ty::ReBound(db, _) if self.binder > db => r,
470+
_ => Region::new_static(self.interner()),
471+
}
439472
}
440473
}

compiler/rustc_type_ir/src/interner.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ use smallvec::SmallVec;
22
use std::fmt::Debug;
33
use std::hash::Hash;
44

5+
use crate::fold::TypeSuperFoldable;
56
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
67
use crate::{
78
new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
89
UniverseIndex,
910
};
1011

11-
pub trait Interner: Sized {
12+
pub trait Interner: Sized + Copy {
1213
type DefId: Copy + Debug + Hash + Eq;
1314
type AdtDef: Copy + Debug + Hash + Eq;
1415

@@ -34,6 +35,7 @@ pub trait Interner: Sized {
3435
+ Into<Self::GenericArg>
3536
+ IntoKind<Kind = TyKind<Self>>
3637
+ TypeSuperVisitable<Self>
38+
+ TypeSuperFoldable<Self>
3739
+ Flags
3840
+ new::Ty<Self>;
3941
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
@@ -57,6 +59,7 @@ pub trait Interner: Sized {
5759
+ IntoKind<Kind = ConstKind<Self>>
5860
+ ConstTy<Self>
5961
+ TypeSuperVisitable<Self>
62+
+ TypeSuperFoldable<Self>
6063
+ Flags
6164
+ new::Const<Self>;
6265
type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;

compiler/rustc_type_ir/src/new.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pub trait Ty<I: Interner<Ty = Self>> {
66

77
pub trait Region<I: Interner<Region = Self>> {
88
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
9+
10+
fn new_static(interner: I) -> Self;
911
}
1012

1113
pub trait Const<I: Interner<Const = Self>> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ check-pass
2+
3+
#![feature(adt_const_params)]
4+
//~^ WARN the feature `adt_const_params` is incomplete
5+
#![feature(with_negative_coherence, negative_impls)]
6+
7+
pub trait A<const K: &'static str> {}
8+
pub trait C {}
9+
10+
11+
struct W<T>(T);
12+
13+
// Negative coherence:
14+
// Proving `W<!T>: !A<"">` requires proving `CONST alias-eq ""`, which requires proving
15+
// `CONST normalizes-to (?1c: &str)`. The type's region is uniquified, so it ends up being
16+
// put in to the canonical vars list with an infer region => ICE.
17+
impl<T> C for T where T: A<""> {}
18+
impl<T> C for W<T> {}
19+
20+
impl<T> !A<CONST> for W<T> {}
21+
const CONST: &str = "";
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/regions-in-canonical.rs:3:12
3+
|
4+
LL | #![feature(adt_const_params)]
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)