Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c67a173

Browse files
committed
pass sub_relations into canonical queries
1 parent 03e4228 commit c67a173

File tree

14 files changed

+342
-318
lines changed

14 files changed

+342
-318
lines changed

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
77
88
use rustc_data_structures::fx::FxHashMap;
9+
use rustc_data_structures::sso::SsoHashMap;
910
use rustc_index::Idx;
1011
use rustc_middle::bug;
1112
use rustc_middle::ty::{
@@ -293,6 +294,7 @@ struct Canonicalizer<'cx, 'tcx> {
293294
// Note that indices is only used once `var_values` is big enough to be
294295
// heap-allocated.
295296
indices: FxHashMap<GenericArg<'tcx>, BoundVar>,
297+
sub_root_lookup_table: SsoHashMap<ty::TyVid, usize>,
296298
canonicalize_mode: &'cx dyn CanonicalizeMode,
297299
needs_canonical_flags: TypeFlags,
298300

@@ -361,7 +363,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
361363
// FIXME: perf problem described in #55921.
362364
ui = ty::UniverseIndex::ROOT;
363365
}
364-
self.canonicalize_ty_var(CanonicalVarKind::Ty(ui), t)
366+
let sub_root = self.get_or_insert_sub_root(vid);
367+
self.canonicalize_ty_var(CanonicalVarKind::Ty { ui, sub_root }, t)
365368
}
366369
}
367370
}
@@ -559,6 +562,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
559562
variables: SmallVec::from_slice(base.variables),
560563
query_state,
561564
indices: FxHashMap::default(),
565+
sub_root_lookup_table: Default::default(),
562566
binder_index: ty::INNERMOST,
563567
};
564568
if canonicalizer.query_state.var_values.spilled() {
@@ -657,6 +661,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
657661
}
658662
}
659663

664+
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
665+
let root_vid = self.infcx.unwrap().sub_root_var(vid);
666+
let idx =
667+
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
668+
ty::BoundVar::from(idx)
669+
}
670+
660671
/// Replaces the universe indexes used in `var_values` with their index in
661672
/// `query_state.universe_map`. This minimizes the maximum universe used in
662673
/// the canonicalized value.
@@ -679,7 +690,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
679690
CanonicalVarKind::Int | CanonicalVarKind::Float => {
680691
return kind;
681692
}
682-
CanonicalVarKind::Ty(u) => CanonicalVarKind::Ty(reverse_universe_map[&u]),
693+
CanonicalVarKind::Ty { ui, sub_root } => {
694+
CanonicalVarKind::Ty { ui: reverse_universe_map[&ui], sub_root }
695+
}
683696
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
684697
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
685698
CanonicalVarKind::PlaceholderTy(placeholder) => {

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

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,12 @@ impl<'tcx> InferCtxt<'tcx> {
8484
variables: &List<CanonicalVarKind<'tcx>>,
8585
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
8686
) -> CanonicalVarValues<'tcx> {
87-
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-
),
87+
let mut var_values = Vec::with_capacity(variables.len());
88+
for info in variables.iter() {
89+
let value = self.instantiate_canonical_var(span, info, &var_values, &universe_map);
90+
var_values.push(value);
9391
}
92+
CanonicalVarValues { var_values: self.tcx.mk_args(&var_values) }
9493
}
9594

9695
/// Given the "info" about a canonical variable, creates a fresh
@@ -105,10 +104,22 @@ impl<'tcx> InferCtxt<'tcx> {
105104
&self,
106105
span: Span,
107106
kind: CanonicalVarKind<'tcx>,
107+
previous_var_values: &[GenericArg<'tcx>],
108108
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
109109
) -> GenericArg<'tcx> {
110110
match kind {
111-
CanonicalVarKind::Ty(ui) => self.next_ty_var_in_universe(span, universe_map(ui)).into(),
111+
CanonicalVarKind::Ty { ui, sub_root } => {
112+
let vid = self.next_ty_vid_in_universe(span, universe_map(ui));
113+
// Fetch the `sub_root` in case it exists.
114+
if let Some(prev) = previous_var_values.get(sub_root.as_usize()) {
115+
if let &ty::Infer(ty::TyVar(sub_root)) = prev.expect_ty().kind() {
116+
self.inner.borrow_mut().type_variables().sub(vid, sub_root);
117+
} else {
118+
unreachable!()
119+
}
120+
}
121+
Ty::new_var(self.tcx, vid).into()
122+
}
112123

113124
CanonicalVarKind::Int => self.next_int_var().into(),
114125

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

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::iter;
1313
use rustc_index::{Idx, IndexVec};
1414
use rustc_middle::arena::ArenaAllocatable;
1515
use rustc_middle::bug;
16+
use rustc_middle::infer::canonical::CanonicalVarKind;
1617
use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
1718
use tracing::{debug, instrument};
1819

@@ -413,35 +414,34 @@ impl<'tcx> InferCtxt<'tcx> {
413414
let mut opt_values: IndexVec<BoundVar, Option<GenericArg<'tcx>>> =
414415
IndexVec::from_elem_n(None, query_response.variables.len());
415416

416-
// In terms of our example above, we are iterating over pairs like:
417-
// [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
418417
for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
419418
{
420419
match result_value.kind() {
421420
GenericArgKind::Type(result_value) => {
422-
// e.g., here `result_value` might be `?0` in the example above...
423-
if let ty::Bound(debruijn, b) = *result_value.kind() {
424-
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
425-
421+
// We disable the instantiation guess for inference variables
422+
// and only use it for placeholders. We need to handle the
423+
// `sub_root` of type inference variables which would make this
424+
// more involved. They are also a lot rarer than region variables.
425+
if let ty::Bound(debruijn, b) = *result_value.kind()
426+
&& !matches!(
427+
query_response.variables[b.var.as_usize()],
428+
CanonicalVarKind::Ty { .. }
429+
)
430+
{
426431
// We only allow a `ty::INNERMOST` index in generic parameters.
427432
assert_eq!(debruijn, ty::INNERMOST);
428433
opt_values[b.var] = Some(*original_value);
429434
}
430435
}
431436
GenericArgKind::Lifetime(result_value) => {
432-
// e.g., here `result_value` might be `'?1` in the example above...
433437
if let ty::ReBound(debruijn, b) = result_value.kind() {
434-
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
435-
436438
// We only allow a `ty::INNERMOST` index in generic parameters.
437439
assert_eq!(debruijn, ty::INNERMOST);
438440
opt_values[b.var] = Some(*original_value);
439441
}
440442
}
441443
GenericArgKind::Const(result_value) => {
442444
if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
443-
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
444-
445445
// We only allow a `ty::INNERMOST` index in generic parameters.
446446
assert_eq!(debruijn, ty::INNERMOST);
447447
opt_values[b.var] = Some(*original_value);
@@ -453,32 +453,31 @@ impl<'tcx> InferCtxt<'tcx> {
453453
// Create result arguments: if we found a value for a
454454
// given variable in the loop above, use that. Otherwise, use
455455
// a fresh inference variable.
456-
let result_args = CanonicalVarValues {
457-
var_values: self.tcx.mk_args_from_iter(
458-
query_response.variables.iter().enumerate().map(|(index, var_kind)| {
459-
if var_kind.universe() != ty::UniverseIndex::ROOT {
460-
// A variable from inside a binder of the query. While ideally these shouldn't
461-
// exist at all, we have to deal with them for now.
462-
self.instantiate_canonical_var(cause.span, var_kind, |u| {
463-
universe_map[u.as_usize()]
464-
})
465-
} else if var_kind.is_existential() {
466-
match opt_values[BoundVar::new(index)] {
467-
Some(k) => k,
468-
None => self.instantiate_canonical_var(cause.span, var_kind, |u| {
469-
universe_map[u.as_usize()]
470-
}),
471-
}
472-
} else {
473-
// For placeholders which were already part of the input, we simply map this
474-
// universal bound variable back the placeholder of the input.
475-
opt_values[BoundVar::new(index)].expect(
476-
"expected placeholder to be unified with itself during response",
477-
)
478-
}
479-
}),
480-
),
481-
};
456+
let mut var_values = Vec::with_capacity(query_response.variables.len());
457+
for (index, kind) in query_response.variables.iter().enumerate() {
458+
let value = if kind.universe() != ty::UniverseIndex::ROOT {
459+
// A variable from inside a binder of the query. While ideally these shouldn't
460+
// exist at all, we have to deal with them for now.
461+
self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
462+
universe_map[u.as_usize()]
463+
})
464+
} else if kind.is_existential() {
465+
match opt_values[BoundVar::new(index)] {
466+
Some(k) => k,
467+
None => self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
468+
universe_map[u.as_usize()]
469+
}),
470+
}
471+
} else {
472+
// For placeholders which were already part of the input, we simply map this
473+
// universal bound variable back the placeholder of the input.
474+
opt_values[BoundVar::new(index)]
475+
.expect("expected placeholder to be unified with itself during response")
476+
};
477+
var_values.push(value);
478+
}
479+
480+
let result_args = CanonicalVarValues { var_values: self.tcx.mk_args(&var_values) };
482481

483482
let mut obligations = PredicateObligations::new();
484483

‎compiler/rustc_infer/src/infer/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
5959
self.root_var(var)
6060
}
6161

62+
fn sub_root_ty_var(&self, var: ty::TyVid) -> ty::TyVid {
63+
self.sub_root_var(var)
64+
}
65+
6266
fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
6367
self.root_const_var(var)
6468
}

‎compiler/rustc_next_trait_solver/src/canonicalizer.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
6767
variables: &'a mut Vec<I::GenericArg>,
6868
var_kinds: Vec<CanonicalVarKind<I>>,
6969
variable_lookup_table: HashMap<I::GenericArg, usize>,
70+
sub_root_lookup_table: HashMap<ty::TyVid, usize>,
7071
binder_index: ty::DebruijnIndex,
7172

7273
/// We only use the debruijn index during lookup. We don't need to
@@ -88,6 +89,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
8889

8990
variables,
9091
variable_lookup_table: Default::default(),
92+
sub_root_lookup_table: Default::default(),
9193
var_kinds: Vec::new(),
9294
binder_index: ty::INNERMOST,
9395

@@ -132,13 +134,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
132134

133135
variables: &mut variables,
134136
variable_lookup_table: Default::default(),
137+
sub_root_lookup_table: Default::default(),
135138
var_kinds: Vec::new(),
136139
binder_index: ty::INNERMOST,
137140

138141
cache: Default::default(),
139142
};
140143
let param_env = param_env.fold_with(&mut env_canonicalizer);
141144
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
145+
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
142146
CanonicalParamEnvCacheEntry {
143147
param_env,
144148
variable_lookup_table: env_canonicalizer.variable_lookup_table,
@@ -164,13 +168,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
164168

165169
variables,
166170
variable_lookup_table: Default::default(),
171+
sub_root_lookup_table: Default::default(),
167172
var_kinds: Vec::new(),
168173
binder_index: ty::INNERMOST,
169174

170175
cache: Default::default(),
171176
};
172177
let param_env = param_env.fold_with(&mut env_canonicalizer);
173178
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
179+
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
174180
(param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds)
175181
}
176182
}
@@ -199,6 +205,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
199205

200206
variables,
201207
variable_lookup_table,
208+
sub_root_lookup_table: Default::default(),
202209
var_kinds,
203210
binder_index: ty::INNERMOST,
204211

@@ -265,6 +272,13 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
265272
ty::BoundVar::from(idx)
266273
}
267274

275+
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
276+
let root_vid = self.delegate.sub_root_ty_var(vid);
277+
let idx =
278+
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
279+
ty::BoundVar::from(idx)
280+
}
281+
268282
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVarKinds) {
269283
let mut var_kinds = self.var_kinds;
270284
// See the rustc-dev-guide section about how we deal with universes
@@ -312,16 +326,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
312326
"ty vid should have been resolved fully before canonicalization"
313327
);
314328

315-
match self.canonicalize_mode {
316-
CanonicalizeMode::Input { .. } => {
317-
CanonicalVarKind::Ty(ty::UniverseIndex::ROOT)
318-
}
319-
CanonicalizeMode::Response { .. } => {
320-
CanonicalVarKind::Ty(self.delegate.universe_of_ty(vid).unwrap_or_else(
321-
|| panic!("ty var should have been resolved: {t:?}"),
322-
))
323-
}
324-
}
329+
let sub_root = self.get_or_insert_sub_root(vid);
330+
let ui = match self.canonicalize_mode {
331+
CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT,
332+
CanonicalizeMode::Response { .. } => self
333+
.delegate
334+
.universe_of_ty(vid)
335+
.unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
336+
};
337+
CanonicalVarKind::Ty { ui, sub_root }
325338
}
326339
ty::IntVar(vid) => {
327340
debug_assert_eq!(

‎compiler/rustc_next_trait_solver/src/delegate.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
5757
where
5858
V: TypeFoldable<Self::Interner>;
5959

60-
fn instantiate_canonical_var_with_infer(
60+
fn instantiate_canonical_var(
6161
&self,
6262
kind: ty::CanonicalVarKind<Self::Interner>,
6363
span: <Self::Interner as Interner>::Span,
64+
var_values: &[<Self::Interner as Interner>::GenericArg],
6465
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
6566
) -> <Self::Interner as Interner>::GenericArg;
67+
6668
fn add_item_bounds_for_hidden_type(
6769
&self,
6870
def_id: <Self::Interner as Interner>::DefId,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /