Skip to content

Commit 4152df6

Browse files
committed
do not canonicalize BoundVar for placeholders
1 parent 326b7e9 commit 4152df6

File tree

23 files changed

+229
-192
lines changed

23 files changed

+229
-192
lines changed

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
173173
match r.kind() {
174174
ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,
175175

176-
ty::RePlaceholder(placeholder) => canonicalizer
177-
.canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r),
176+
ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
177+
CanonicalVarKind::PlaceholderRegion(placeholder.universe),
178+
r,
179+
),
178180

179181
ty::ReVar(vid) => {
180182
let universe = infcx
@@ -288,7 +290,7 @@ struct Canonicalizer<'cx, 'tcx> {
288290
/// Set to `None` to disable the resolution of inference variables.
289291
infcx: Option<&'cx InferCtxt<'tcx>>,
290292
tcx: TyCtxt<'tcx>,
291-
variables: SmallVec<[CanonicalVarKind<'tcx>; 8]>,
293+
variables: SmallVec<[CanonicalVarKind; 8]>,
292294
query_state: &'cx mut OriginalQueryValues<'tcx>,
293295
// Note that indices is only used once `var_values` is big enough to be
294296
// heap-allocated.
@@ -390,11 +392,13 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
390392
bug!("encountered a fresh type during canonicalization")
391393
}
392394

393-
ty::Placeholder(mut placeholder) => {
394-
if !self.canonicalize_mode.preserve_universes() {
395-
placeholder.universe = ty::UniverseIndex::ROOT;
396-
}
397-
self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
395+
ty::Placeholder(placeholder) => {
396+
let universe = if self.canonicalize_mode.preserve_universes() {
397+
placeholder.universe
398+
} else {
399+
ty::UniverseIndex::ROOT
400+
};
401+
self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(universe), t)
398402
}
399403

400404
ty::Bound(debruijn, _) => {
@@ -481,8 +485,13 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
481485
}
482486
}
483487
ty::ConstKind::Placeholder(placeholder) => {
488+
let universe = if self.canonicalize_mode.preserve_universes() {
489+
placeholder.universe
490+
} else {
491+
ty::UniverseIndex::ROOT
492+
};
484493
return self
485-
.canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct);
494+
.canonicalize_const_var(CanonicalVarKind::PlaceholderConst(universe), ct);
486495
}
487496
_ => {}
488497
}
@@ -588,11 +597,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
588597
/// or returns an existing variable if `kind` has already been
589598
/// seen. `kind` is expected to be an unbound variable (or
590599
/// potentially a free region).
591-
fn canonical_var(
592-
&mut self,
593-
var_kind: CanonicalVarKind<'tcx>,
594-
value: GenericArg<'tcx>,
595-
) -> BoundVar {
600+
fn canonical_var(&mut self, var_kind: CanonicalVarKind, value: GenericArg<'tcx>) -> BoundVar {
596601
let Canonicalizer { variables, query_state, indices, .. } = self;
597602

598603
let var_values = &mut query_state.var_values;
@@ -655,7 +660,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
655660
/// Replaces the universe indexes used in `var_values` with their index in
656661
/// `query_state.universe_map`. This minimizes the maximum universe used in
657662
/// the canonicalized value.
658-
fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarKind<'tcx>; 8]> {
663+
fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarKind; 8]> {
659664
if self.query_state.universe_map.len() == 1 {
660665
return self.variables;
661666
}
@@ -679,23 +684,14 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
679684
}
680685
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
681686
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
682-
CanonicalVarKind::PlaceholderTy(placeholder) => {
683-
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
684-
universe: reverse_universe_map[&placeholder.universe],
685-
..placeholder
686-
})
687+
CanonicalVarKind::PlaceholderTy(ui) => {
688+
CanonicalVarKind::PlaceholderTy(reverse_universe_map[&ui])
687689
}
688-
CanonicalVarKind::PlaceholderRegion(placeholder) => {
689-
CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
690-
universe: reverse_universe_map[&placeholder.universe],
691-
..placeholder
692-
})
690+
CanonicalVarKind::PlaceholderRegion(ui) => {
691+
CanonicalVarKind::PlaceholderRegion(reverse_universe_map[&ui])
693692
}
694-
CanonicalVarKind::PlaceholderConst(placeholder) => {
695-
CanonicalVarKind::PlaceholderConst(ty::Placeholder {
696-
universe: reverse_universe_map[&placeholder.universe],
697-
..placeholder
698-
})
693+
CanonicalVarKind::PlaceholderConst(ui) => {
694+
CanonicalVarKind::PlaceholderConst(reverse_universe_map[&ui])
699695
}
700696
})
701697
.collect()
@@ -725,7 +721,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
725721
/// representing the region `r`; return a region referencing it.
726722
fn canonical_var_for_region(
727723
&mut self,
728-
var_kind: CanonicalVarKind<'tcx>,
724+
var_kind: CanonicalVarKind,
729725
r: ty::Region<'tcx>,
730726
) -> ty::Region<'tcx> {
731727
let var = self.canonical_var(var_kind, r.into());
@@ -737,14 +733,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
737733
/// if `ty_var` is bound to anything; if so, canonicalize
738734
/// *that*. Otherwise, create a new canonical variable for
739735
/// `ty_var`.
740-
fn canonicalize_ty_var(
741-
&mut self,
742-
var_kind: CanonicalVarKind<'tcx>,
743-
ty_var: Ty<'tcx>,
744-
) -> Ty<'tcx> {
736+
fn canonicalize_ty_var(&mut self, var_kind: CanonicalVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
745737
debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var)));
746738
let var = self.canonical_var(var_kind, ty_var.into());
747-
Ty::new_bound(self.tcx, self.binder_index, var.into())
739+
Ty::new_bound(self.tcx, self.binder_index, ty::BoundTy::new_anon(var))
748740
}
749741

750742
/// Given a type variable `const_var` of the given kind, first check
@@ -753,7 +745,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
753745
/// `const_var`.
754746
fn canonicalize_const_var(
755747
&mut self,
756-
var_kind: CanonicalVarKind<'tcx>,
748+
var_kind: CanonicalVarKind,
757749
ct_var: ty::Const<'tcx>,
758750
) -> ty::Const<'tcx> {
759751
debug_assert!(

compiler/rustc_infer/src/infer/canonical/mod.rs

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -81,30 +81,27 @@ impl<'tcx> InferCtxt<'tcx> {
8181
fn instantiate_canonical_vars(
8282
&self,
8383
span: Span,
84-
variables: &List<CanonicalVarKind<'tcx>>,
84+
variables: &List<CanonicalVarKind>,
8585
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
8686
) -> CanonicalVarValues<'tcx> {
8787
CanonicalVarValues {
88-
var_values: self.tcx.mk_args_from_iter(
89-
variables
90-
.iter()
91-
.map(|kind| self.instantiate_canonical_var(span, kind, &universe_map)),
92-
),
88+
var_values: self.tcx.mk_args_from_iter(variables.iter().enumerate().map(
89+
|(at_index, kind)| {
90+
self.instantiate_canonical_var(span, at_index, kind, &universe_map)
91+
},
92+
)),
9393
}
9494
}
9595

96-
/// Given the "info" about a canonical variable, creates a fresh
97-
/// variable for it. If this is an existentially quantified
98-
/// variable, then you'll get a new inference variable; if it is a
99-
/// universally quantified variable, you get a placeholder.
96+
/// Given the "info" about a canonical variable, creates a fresh variable for it.
10097
///
101-
/// FIXME(-Znext-solver): This is public because it's used by the
102-
/// new trait solver which has a different canonicalization routine.
103-
/// We should somehow deduplicate all of this.
104-
pub fn instantiate_canonical_var(
98+
/// This ICEs if the input is not an existential variable. Handle placeholders separately
99+
/// or call [Self::instantiate_canonical_var] instead.
100+
#[inline]
101+
pub fn instantiate_existential_canonical_var(
105102
&self,
106103
span: Span,
107-
kind: CanonicalVarKind<'tcx>,
104+
kind: CanonicalVarKind,
108105
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
109106
) -> GenericArg<'tcx> {
110107
match kind {
@@ -121,32 +118,68 @@ impl<'tcx> InferCtxt<'tcx> {
121118
ty.into()
122119
}
123120

124-
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
125-
let universe_mapped = universe_map(universe);
126-
let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound };
127-
Ty::new_placeholder(self.tcx, placeholder_mapped).into()
128-
}
129-
130121
CanonicalVarKind::Region(ui) => self
131122
.next_region_var_in_universe(
132123
RegionVariableOrigin::MiscVariable(span),
133124
universe_map(ui),
134125
)
135126
.into(),
136127

137-
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => {
128+
CanonicalVarKind::Const(ui) => {
129+
self.next_const_var_in_universe(span, universe_map(ui)).into()
130+
}
131+
132+
CanonicalVarKind::PlaceholderRegion(_)
133+
| CanonicalVarKind::PlaceholderTy(_)
134+
| CanonicalVarKind::PlaceholderConst(_) => unreachable!(),
135+
}
136+
}
137+
138+
/// Given the "info" about a canonical variable, creates a fresh
139+
/// variable for it. If this is an existentially quantified
140+
/// variable, then you'll get a new inference variable; if it is a
141+
/// universally quantified variable, you get a placeholder.
142+
///
143+
/// FIXME(-Znext-solver): This is public because it's used by the
144+
/// new trait solver which has a different canonicalization routine.
145+
/// We should somehow deduplicate all of this.
146+
pub fn instantiate_canonical_var(
147+
&self,
148+
span: Span,
149+
at_index: usize,
150+
kind: CanonicalVarKind,
151+
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
152+
) -> GenericArg<'tcx> {
153+
match kind {
154+
CanonicalVarKind::Region(_) | CanonicalVarKind::Ty(_) | CanonicalVarKind::Const(_) => {
155+
self.instantiate_existential_canonical_var(span, kind, universe_map)
156+
}
157+
158+
CanonicalVarKind::PlaceholderTy(universe) => {
159+
let var = ty::BoundVar::from_usize(at_index);
138160
let universe_mapped = universe_map(universe);
139-
let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound };
140-
ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
161+
let placeholder = ty::PlaceholderType {
162+
universe: universe_mapped,
163+
bound: ty::BoundTy::new_anon(var),
164+
};
165+
Ty::new_placeholder(self.tcx, placeholder).into()
141166
}
142167

143-
CanonicalVarKind::Const(ui) => {
144-
self.next_const_var_in_universe(span, universe_map(ui)).into()
168+
CanonicalVarKind::PlaceholderRegion(universe) => {
169+
let var = ty::BoundVar::from_usize(at_index);
170+
let universe_mapped = universe_map(universe);
171+
let placeholder = ty::PlaceholderRegion {
172+
universe: universe_mapped,
173+
bound: ty::BoundRegion::new_anon(var),
174+
};
175+
ty::Region::new_placeholder(self.tcx, placeholder).into()
145176
}
146-
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
177+
178+
CanonicalVarKind::PlaceholderConst(universe) => {
179+
let var = ty::BoundVar::from_usize(at_index);
147180
let universe_mapped = universe_map(universe);
148-
let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
149-
ty::Const::new_placeholder(self.tcx, placeholder_mapped).into()
181+
let placeholder = ty::PlaceholderConst { universe: universe_mapped, bound: var };
182+
ty::Const::new_placeholder(self.tcx, placeholder).into()
150183
}
151184
}
152185
}

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,15 +449,17 @@ impl<'tcx> InferCtxt<'tcx> {
449449
if var_kind.universe() != ty::UniverseIndex::ROOT {
450450
// A variable from inside a binder of the query. While ideally these shouldn't
451451
// exist at all, we have to deal with them for now.
452-
self.instantiate_canonical_var(cause.span, var_kind, |u| {
452+
self.instantiate_canonical_var(cause.span, index, var_kind, |u| {
453453
universe_map[u.as_usize()]
454454
})
455455
} else if var_kind.is_existential() {
456456
match opt_values[BoundVar::new(index)] {
457457
Some(k) => k,
458-
None => self.instantiate_canonical_var(cause.span, var_kind, |u| {
459-
universe_map[u.as_usize()]
460-
}),
458+
None => {
459+
self.instantiate_canonical_var(cause.span, index, var_kind, |u| {
460+
universe_map[u.as_usize()]
461+
})
462+
}
461463
}
462464
} else {
463465
// For placeholders which were already part of the input, we simply map this

compiler/rustc_middle/src/infer/canonical.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ use crate::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt}
3535

3636
pub type CanonicalQueryInput<'tcx, V> = ir::CanonicalQueryInput<TyCtxt<'tcx>, V>;
3737
pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
38-
pub type CanonicalVarKind<'tcx> = ir::CanonicalVarKind<TyCtxt<'tcx>>;
38+
pub type CanonicalVarKind = ir::CanonicalVarKind;
3939
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
40-
pub type CanonicalVarKinds<'tcx> = &'tcx List<CanonicalVarKind<'tcx>>;
40+
pub type CanonicalVarKinds<'tcx> = &'tcx List<CanonicalVarKind>;
4141

4242
/// When we canonicalize a value to form a query, we wind up replacing
4343
/// various parts of it with canonical variables. This struct stores

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
314314
fn decode(decoder: &mut D) -> Self {
315315
let len = decoder.read_usize();
316316
decoder.interner().mk_canonical_var_infos_from_iter(
317-
(0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
317+
(0..len).map::<CanonicalVarKind, _>(|_| Decodable::decode(decoder)),
318318
)
319319
}
320320
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
108108
}
109109
type LocalDefIds = &'tcx ty::List<LocalDefId>;
110110
type CanonicalVarKinds = CanonicalVarKinds<'tcx>;
111-
fn mk_canonical_var_kinds(
112-
self,
113-
kinds: &[ty::CanonicalVarKind<Self>],
114-
) -> Self::CanonicalVarKinds {
111+
fn mk_canonical_var_kinds(self, kinds: &[ty::CanonicalVarKind]) -> Self::CanonicalVarKinds {
115112
self.mk_canonical_var_kinds(kinds)
116113
}
117114

@@ -836,7 +833,7 @@ pub struct CtxtInterners<'tcx> {
836833
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
837834
args: InternedSet<'tcx, GenericArgs<'tcx>>,
838835
type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
839-
canonical_var_kinds: InternedSet<'tcx, List<CanonicalVarKind<'tcx>>>,
836+
canonical_var_kinds: InternedSet<'tcx, List<CanonicalVarKind>>,
840837
region: InternedSet<'tcx, RegionKind<'tcx>>,
841838
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
842839
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
@@ -2678,7 +2675,7 @@ slice_interners!(
26782675
const_lists: pub mk_const_list(Const<'tcx>),
26792676
args: pub mk_args(GenericArg<'tcx>),
26802677
type_lists: pub mk_type_list(Ty<'tcx>),
2681-
canonical_var_kinds: pub mk_canonical_var_kinds(CanonicalVarKind<'tcx>),
2678+
canonical_var_kinds: pub mk_canonical_var_kinds(CanonicalVarKind),
26822679
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
26832680
projs: pub mk_projs(ProjectionKind),
26842681
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
@@ -3058,7 +3055,7 @@ impl<'tcx> TyCtxt<'tcx> {
30583055
pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
30593056
where
30603057
I: Iterator<Item = T>,
3061-
T: CollectAndApply<CanonicalVarKind<'tcx>, &'tcx List<CanonicalVarKind<'tcx>>>,
3058+
T: CollectAndApply<CanonicalVarKind, &'tcx List<CanonicalVarKind>>,
30623059
{
30633060
T::collect_and_apply(iter, |xs| self.mk_canonical_var_kinds(xs))
30643061
}

compiler/rustc_middle/src/ty/region.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,23 @@ pub struct BoundRegion {
437437
pub kind: BoundRegionKind,
438438
}
439439

440+
impl BoundRegion {
441+
pub fn new_anon(var: BoundVar) -> BoundRegion {
442+
BoundRegion { var, kind: BoundRegionKind::Anon }
443+
}
444+
}
445+
440446
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
447+
fn new_anon(var: BoundVar) -> BoundRegion {
448+
Self::new_anon(var)
449+
}
450+
441451
fn var(self) -> BoundVar {
442452
self.var
443453
}
444454

445-
fn assert_eq(self, var: ty::BoundVariableKind) {
446-
assert_eq!(self.kind, var.expect_region())
455+
fn assert_eq(self, kind: ty::BoundVariableKind) {
456+
assert_eq!(self.kind, kind.expect_region())
447457
}
448458
}
449459

0 commit comments

Comments
 (0)