Skip to content

Commit 7fac078

Browse files
Auto merge of #140375 - lcnr:subrelations-infcx, r=<try>
eagerly compute `sub_relations` again
2 parents 4356e83 + 739367a commit 7fac078

File tree

53 files changed

+599
-706
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+599
-706
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
2121
use rustc_session::Session;
2222
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
2323
use rustc_trait_selection::error_reporting::TypeErrCtxt;
24-
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
2524
use rustc_trait_selection::traits::{
2625
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
2726
};
@@ -183,14 +182,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183182
///
184183
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
185184
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
186-
let mut sub_relations = SubRelations::default();
187-
sub_relations.add_constraints(
188-
self,
189-
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
190-
);
191185
TypeErrCtxt {
192186
infcx: &self.infcx,
193-
sub_relations: RefCell::new(sub_relations),
194187
typeck_results: Some(self.typeck_results.borrow()),
195188
fallback_has_occurred: self.fallback_has_occurred.get(),
196189
normalize_fn_sig: Box::new(|fn_sig| {

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

Lines changed: 18 additions & 10 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::{
@@ -17,7 +18,7 @@ use tracing::debug;
1718

1819
use crate::infer::InferCtxt;
1920
use crate::infer::canonical::{
20-
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarKind, OriginalQueryValues,
21+
Canonical, CanonicalQueryInput, CanonicalVarKind, OriginalQueryValues,
2122
};
2223

2324
impl<'tcx> InferCtxt<'tcx> {
@@ -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,10 +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(
365-
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
366-
t,
367-
)
366+
let sub_root = self.get_or_insert_sub_root(vid);
367+
self.canonicalize_ty_var(CanonicalVarKind::Ty { ui, sub_root }, t)
368368
}
369369
}
370370
}
@@ -374,15 +374,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
374374
if nt != t {
375375
return self.fold_ty(nt);
376376
} else {
377-
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
377+
self.canonicalize_ty_var(CanonicalVarKind::Int, t)
378378
}
379379
}
380380
ty::Infer(ty::FloatVar(vid)) => {
381381
let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid);
382382
if nt != t {
383383
return self.fold_ty(nt);
384384
} else {
385-
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t)
385+
self.canonicalize_ty_var(CanonicalVarKind::Float, t)
386386
}
387387
}
388388

@@ -562,6 +562,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
562562
variables: SmallVec::from_slice(base.variables),
563563
query_state,
564564
indices: FxHashMap::default(),
565+
sub_root_lookup_table: Default::default(),
565566
binder_index: ty::INNERMOST,
566567
};
567568
if canonicalizer.query_state.var_values.spilled() {
@@ -660,6 +661,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
660661
}
661662
}
662663

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+
663671
/// Replaces the universe indexes used in `var_values` with their index in
664672
/// `query_state.universe_map`. This minimizes the maximum universe used in
665673
/// the canonicalized value.
@@ -679,11 +687,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
679687
self.variables
680688
.iter()
681689
.map(|&kind| match kind {
682-
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
690+
CanonicalVarKind::Int | CanonicalVarKind::Float => {
683691
return kind;
684692
}
685-
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
686-
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
693+
CanonicalVarKind::Ty { ui, sub_root } => {
694+
CanonicalVarKind::Ty { ui: reverse_universe_map[&ui], sub_root }
687695
}
688696
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
689697
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),

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

Lines changed: 19 additions & 15 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,21 +104,26 @@ 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(ty_kind) => {
112-
let ty = match ty_kind {
113-
CanonicalTyVarKind::General(ui) => {
114-
self.next_ty_var_in_universe(span, universe_map(ui))
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!()
115119
}
120+
}
121+
Ty::new_var(self.tcx, vid).into()
122+
}
116123

117-
CanonicalTyVarKind::Int => self.next_int_var(),
124+
CanonicalVarKind::Int => self.next_int_var().into(),
118125

119-
CanonicalTyVarKind::Float => self.next_float_var(),
120-
};
121-
ty.into()
122-
}
126+
CanonicalVarKind::Float => self.next_float_var().into(),
123127

124128
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
125129
let universe_mapped = universe_map(universe);

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

Lines changed: 32 additions & 27 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

@@ -420,7 +421,12 @@ impl<'tcx> InferCtxt<'tcx> {
420421
match result_value.kind() {
421422
GenericArgKind::Type(result_value) => {
422423
// e.g., here `result_value` might be `?0` in the example above...
423-
if let ty::Bound(debruijn, b) = *result_value.kind() {
424+
if let ty::Bound(debruijn, b) = *result_value.kind()
425+
&& !matches!(
426+
query_response.variables[b.var.as_usize()],
427+
CanonicalVarKind::Ty { .. }
428+
)
429+
{
424430
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
425431

426432
// We only allow a `ty::INNERMOST` index in generic parameters.
@@ -453,32 +459,31 @@ impl<'tcx> InferCtxt<'tcx> {
453459
// Create result arguments: if we found a value for a
454460
// given variable in the loop above, use that. Otherwise, use
455461
// 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-
};
462+
let mut var_values = Vec::with_capacity(query_response.variables.len());
463+
for (index, kind) in query_response.variables.iter().enumerate() {
464+
let value = if kind.universe() != ty::UniverseIndex::ROOT {
465+
// A variable from inside a binder of the query. While ideally these shouldn't
466+
// exist at all, we have to deal with them for now.
467+
self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
468+
universe_map[u.as_usize()]
469+
})
470+
} else if kind.is_existential() {
471+
match opt_values[BoundVar::new(index)] {
472+
Some(k) => k,
473+
None => self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
474+
universe_map[u.as_usize()]
475+
}),
476+
}
477+
} else {
478+
// For placeholders which were already part of the input, we simply map this
479+
// universal bound variable back the placeholder of the input.
480+
opt_values[BoundVar::new(index)]
481+
.expect("expected placeholder to be unified with itself during response")
482+
};
483+
var_values.push(value);
484+
}
485+
486+
let result_args = CanonicalVarValues { var_values: self.tcx.mk_args(&var_values) };
482487

483488
let mut obligations = PredicateObligations::new();
484489

compiler/rustc_infer/src/infer/context.rs

Lines changed: 8 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
}
@@ -179,6 +183,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
179183
self.inner.borrow_mut().type_variables().equate(a, b);
180184
}
181185

186+
fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
187+
self.sub_ty_vids_raw(a, b);
188+
}
189+
182190
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
183191
self.inner.borrow_mut().int_unification_table().union(a, b);
184192
}

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,14 @@ impl<'tcx> InferCtxt<'tcx> {
11241124
self.inner.borrow_mut().type_variables().root_var(var)
11251125
}
11261126

1127+
pub fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
1128+
self.inner.borrow_mut().type_variables().sub(a, b);
1129+
}
1130+
1131+
pub fn sub_root_var(&self, var: ty::TyVid) -> ty::TyVid {
1132+
self.inner.borrow_mut().type_variables().sub_root_var(var)
1133+
}
1134+
11271135
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
11281136
self.inner.borrow_mut().const_unification_table().find(var).vid
11291137
}

compiler/rustc_infer/src/infer/relate/generalize.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
519519
let origin = inner.type_variables().var_origin(vid);
520520
let new_var_id =
521521
inner.type_variables().new_var(self.for_universe, origin);
522+
// Record that `vid` and `new_var_id` have to be subtypes
523+
// of each other. This is currently only used for diagnostics.
524+
// To see why, see the docs in the `type_variables` module.
525+
inner.type_variables().sub(vid, new_var_id);
522526
// If we're in the new solver and create a new inference
523527
// variable inside of an alias we eagerly constrain that
524528
// inference variable to prevent unexpected ambiguity errors.

compiler/rustc_infer/src/infer/snapshot/undo_log.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct Snapshot<'tcx> {
2020
pub(crate) enum UndoLog<'tcx> {
2121
DuplicateOpaqueType,
2222
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
23-
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
23+
TypeVariables(type_variable::UndoLog<'tcx>),
2424
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
2525
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
2626
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
@@ -49,6 +49,8 @@ impl_from! {
4949
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
5050

5151
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
52+
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>),
53+
TypeVariables(type_variable::UndoLog<'tcx>),
5254
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
5355
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
5456

0 commit comments

Comments
 (0)