Skip to content

Commit 9613271

Browse files
committed
Auto merge of #140480 - lcnr:subrelations-infcx-perf, r=<try>
[for errs] perf run `sub_relations` change r? `@compiler-errors`
2 parents efcbb94 + 50a6fb2 commit 9613271

File tree

23 files changed

+151
-204
lines changed

23 files changed

+151
-204
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1919
use rustc_session::Session;
2020
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
2121
use rustc_trait_selection::error_reporting::TypeErrCtxt;
22-
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
2322
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
2423

2524
use crate::coercion::DynamicCoerceMany;
@@ -177,14 +176,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
177176
///
178177
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
179178
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
180-
let mut sub_relations = SubRelations::default();
181-
sub_relations.add_constraints(
182-
self,
183-
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
184-
);
185179
TypeErrCtxt {
186180
infcx: &self.infcx,
187-
sub_relations: RefCell::new(sub_relations),
188181
typeck_results: Some(self.typeck_results.borrow()),
189182
fallback_has_occurred: self.fallback_has_occurred.get(),
190183
normalize_fn_sig: Box::new(|fn_sig| {

compiler/rustc_hir_typeck/src/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12131213
debug!("pick_all_method: step={:?}", step);
12141214
// skip types that are from a type error or that would require dereferencing
12151215
// a raw pointer
1216-
!step.self_ty.references_error() && !step.from_unsafe_deref
1216+
!step.self_ty.value.references_error() && !step.from_unsafe_deref
12171217
})
12181218
.find_map(|step| {
12191219
let InferOk { value: self_ty, obligations: _ } = self

compiler/rustc_hir_typeck/src/writeback.rs

+1-21
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_errors::ErrorGuaranteed;
99
use rustc_hir::intravisit::{self, InferKind, Visitor};
1010
use rustc_hir::{self as hir, AmbigArg, HirId};
1111
use rustc_infer::traits::solve::Goal;
12-
use rustc_middle::span_bug;
1312
use rustc_middle::traits::ObligationCause;
1413
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
1514
use rustc_middle::ty::{
@@ -513,15 +512,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
513512
self.typeck_results.user_provided_types_mut().extend(
514513
fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| {
515514
let hir_id = HirId { owner: common_hir_owner, local_id };
516-
517-
if cfg!(debug_assertions) && c_ty.has_infer() {
518-
span_bug!(
519-
hir_id.to_span(self.fcx.tcx),
520-
"writeback: `{:?}` has inference variables",
521-
c_ty
522-
);
523-
};
524-
525515
(hir_id, *c_ty)
526516
}),
527517
);
@@ -532,17 +522,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
532522
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
533523

534524
self.typeck_results.user_provided_sigs.extend_unord(
535-
fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
536-
if cfg!(debug_assertions) && c_sig.has_infer() {
537-
span_bug!(
538-
self.fcx.tcx.def_span(def_id),
539-
"writeback: `{:?}` has inference variables",
540-
c_sig
541-
);
542-
};
543-
544-
(def_id, *c_sig)
545-
}),
525+
fcx_typeck_results.user_provided_sigs.items().map(|(def_id, c_sig)| (*def_id, *c_sig)),
546526
);
547527
}
548528

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

+6-17
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ use tracing::debug;
1717

1818
use crate::infer::InferCtxt;
1919
use crate::infer::canonical::{
20-
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind,
21-
OriginalQueryValues,
20+
Canonical, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
2221
};
2322

2423
impl<'tcx> InferCtxt<'tcx> {
@@ -368,9 +367,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
368367
ui = ty::UniverseIndex::ROOT;
369368
}
370369
self.canonicalize_ty_var(
371-
CanonicalVarInfo {
372-
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
373-
},
370+
CanonicalVarInfo { kind: CanonicalVarKind::Ty(ui) },
374371
t,
375372
)
376373
}
@@ -382,21 +379,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
382379
if nt != t {
383380
return self.fold_ty(nt);
384381
} else {
385-
self.canonicalize_ty_var(
386-
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
387-
t,
388-
)
382+
self.canonicalize_ty_var(CanonicalVarInfo { kind: CanonicalVarKind::Int }, t)
389383
}
390384
}
391385
ty::Infer(ty::FloatVar(vid)) => {
392386
let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid);
393387
if nt != t {
394388
return self.fold_ty(nt);
395389
} else {
396-
self.canonicalize_ty_var(
397-
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
398-
t,
399-
)
390+
self.canonicalize_ty_var(CanonicalVarInfo { kind: CanonicalVarKind::Float }, t)
400391
}
401392
}
402393

@@ -690,12 +681,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
690681
.iter()
691682
.map(|v| CanonicalVarInfo {
692683
kind: match v.kind {
693-
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
684+
CanonicalVarKind::Int | CanonicalVarKind::Float => {
694685
return *v;
695686
}
696-
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
697-
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
698-
}
687+
CanonicalVarKind::Ty(u) => CanonicalVarKind::Ty(reverse_universe_map[&u]),
699688
CanonicalVarKind::Region(u) => {
700689
CanonicalVarKind::Region(reverse_universe_map[&u])
701690
}

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

+3-12
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,9 @@ impl<'tcx> InferCtxt<'tcx> {
108108
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
109109
) -> GenericArg<'tcx> {
110110
match cv_info.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))
115-
}
116-
117-
CanonicalTyVarKind::Int => self.next_int_var(),
118-
119-
CanonicalTyVarKind::Float => self.next_float_var(),
120-
};
121-
ty.into()
122-
}
111+
CanonicalVarKind::Ty(ui) => self.next_ty_var_in_universe(span, universe_map(ui)).into(),
112+
CanonicalVarKind::Int => self.next_int_var().into(),
113+
CanonicalVarKind::Float => self.next_float_var().into(),
123114

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

compiler/rustc_infer/src/infer/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
125125
self.inner.borrow_mut().type_variables().equate(a, b);
126126
}
127127

128+
fn sub_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
129+
self.inner.borrow_mut().type_variables().sub(a, b);
130+
}
131+
128132
fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) {
129133
self.inner.borrow_mut().int_unification_table().union(a, b);
130134
}

compiler/rustc_infer/src/infer/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ impl<'tcx> InferCtxt<'tcx> {
733733
let r_b = self.shallow_resolve(predicate.skip_binder().b);
734734
match (r_a.kind(), r_b.kind()) {
735735
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
736+
self.inner.borrow_mut().type_variables().sub(a_vid, b_vid);
736737
return Err((a_vid, b_vid));
737738
}
738739
_ => {}
@@ -1065,6 +1066,10 @@ impl<'tcx> InferCtxt<'tcx> {
10651066
self.inner.borrow_mut().type_variables().root_var(var)
10661067
}
10671068

1069+
pub fn sub_root_var(&self, var: ty::TyVid) -> ty::TyVid {
1070+
self.inner.borrow_mut().type_variables().sub_root_var(var)
1071+
}
1072+
10681073
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
10691074
self.inner.borrow_mut().const_unification_table().find(var).vid
10701075
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
503503
let origin = inner.type_variables().var_origin(vid);
504504
let new_var_id =
505505
inner.type_variables().new_var(self.for_universe, origin);
506+
// Record that `vid` and `new_var_id` have to be subtypes
507+
// of each other. This is currently only used for diagnostics.
508+
// To see why, see the docs in the `type_variables` module.
509+
inner.type_variables().sub(vid, new_var_id);
506510
// If we're in the new solver and create a new inference
507511
// variable inside of an alias we eagerly constrain that
508512
// inference variable to prevent unexpected ambiguity errors.

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Snapshot<'tcx> {
1818
#[derive(Clone)]
1919
pub(crate) enum UndoLog<'tcx> {
2020
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
21-
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
21+
TypeVariables(type_variable::UndoLog<'tcx>),
2222
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
2323
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
2424
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
@@ -44,7 +44,9 @@ macro_rules! impl_from {
4444
impl_from! {
4545
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
4646

47+
TypeVariables(type_variable::UndoLog<'tcx>),
4748
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
49+
TypeVariables(sv::UndoLog<ut::Delegate<ty::TyVid>>),
4850
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
4951
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
5052

compiler/rustc_infer/src/infer/type_variable.rs

+76-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,33 @@ use tracing::debug;
1313

1414
use crate::infer::InferCtxtUndoLogs;
1515

16-
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
17-
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
18-
self.eq_relations.reverse(undo)
16+
/// Represents a single undo-able action that affects a type inference variable.
17+
#[derive(Clone)]
18+
pub(crate) enum UndoLog<'tcx> {
19+
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
20+
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
21+
}
22+
23+
/// Convert from a specific kind of undo to the more general UndoLog
24+
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
25+
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
26+
UndoLog::EqRelation(l)
27+
}
28+
}
29+
30+
/// Convert from a specific kind of undo to the more general UndoLog
31+
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
32+
fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
33+
UndoLog::SubRelation(l)
34+
}
35+
}
36+
37+
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
38+
fn reverse(&mut self, undo: UndoLog<'tcx>) {
39+
match undo {
40+
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
41+
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
42+
}
1943
}
2044
}
2145

@@ -27,6 +51,24 @@ pub(crate) struct TypeVariableStorage<'tcx> {
2751
/// constraint `?X == ?Y`. This table also stores, for each key,
2852
/// the known value.
2953
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
54+
55+
/// Only used by `-Znext-solver` andfor diagnostics.
56+
///
57+
/// When reporting ambiguity errors, we sometimes want to
58+
/// treat all inference vars which are subtypes of each
59+
/// others as if they are equal. For this case we compute
60+
/// the transitive closure of our subtype obligations here.
61+
///
62+
/// E.g. when encountering ambiguity errors, we want to suggest
63+
/// specifying some method argument or to add a type annotation
64+
/// to a local variable. Because subtyping cannot change the
65+
/// shape of a type, it's fine if the cause of the ambiguity error
66+
/// is only related to the suggested variable via subtyping.
67+
///
68+
/// Even for something like `let x = returns_arg(); x.method();` the
69+
/// type of `x` is only a supertype of the argument of `returns_arg`. We
70+
/// still want to suggest specifying the type of the argument.
71+
sub_relations: ut::UnificationTableStorage<ty::TyVid>,
3072
}
3173

3274
pub(crate) struct TypeVariableTable<'a, 'tcx> {
@@ -109,6 +151,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
109151
debug_assert!(self.probe(a).is_unknown());
110152
debug_assert!(self.probe(b).is_unknown());
111153
self.eq_relations().union(a, b);
154+
self.sub_relations().union(a, b);
155+
}
156+
157+
/// Records that `a <: b`, depending on `dir`.
158+
///
159+
/// Precondition: neither `a` nor `b` are known.
160+
pub(crate) fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
161+
debug_assert!(self.probe(a).is_unknown());
162+
debug_assert!(self.probe(b).is_unknown());
163+
self.sub_relations().union(a, b);
112164
}
113165

114166
/// Instantiates `vid` with the type `ty`.
@@ -142,6 +194,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
142194
origin: TypeVariableOrigin,
143195
) -> ty::TyVid {
144196
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
197+
198+
let sub_key = self.sub_relations().new_key(());
199+
debug_assert_eq!(eq_key.vid, sub_key);
200+
145201
let index = self.storage.values.push(TypeVariableData { origin });
146202
debug_assert_eq!(eq_key.vid, index);
147203

@@ -164,6 +220,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
164220
self.eq_relations().find(vid).vid
165221
}
166222

223+
/// Returns the "root" variable of `vid` in the `sub_relations`
224+
/// equivalence table. All type variables that have been are
225+
/// related via equality or subtyping will yield the same root
226+
/// variable (per the union-find algorithm), so `sub_root_var(a)
227+
/// == sub_root_var(b)` implies that:
228+
/// ```text
229+
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
230+
/// ```
231+
pub(crate) fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
232+
self.sub_relations().find(vid)
233+
}
234+
167235
/// Retrieves the type to which `vid` has been instantiated, if
168236
/// any.
169237
pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
@@ -181,6 +249,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
181249
self.storage.eq_relations.with_log(self.undo_log)
182250
}
183251

252+
#[inline]
253+
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
254+
self.storage.sub_relations.with_log(self.undo_log)
255+
}
256+
184257
/// Returns a range of the type variables created during the snapshot.
185258
pub(crate) fn vars_since_snapshot(
186259
&mut self,

compiler/rustc_middle/src/infer/canonical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_data_structures::fx::FxHashMap;
2727
use rustc_data_structures::sync::Lock;
2828
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
2929
pub use rustc_type_ir as ir;
30-
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
30+
pub use rustc_type_ir::CanonicalVarKind;
3131
use smallvec::SmallVec;
3232

3333
use crate::mir::ConstraintCategory;

compiler/rustc_middle/src/ty/structural_impls.rs

-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use rustc_type_ir::{ConstKind, TypeFolder, VisitorResult, try_visit};
1313

1414
use super::print::PrettyPrinter;
1515
use super::{GenericArg, GenericArgKind, Pattern, Region};
16-
use crate::infer::canonical::CanonicalVarInfos;
1716
use crate::mir::PlaceElem;
1817
use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths};
1918
use crate::ty::{
@@ -779,5 +778,4 @@ list_fold! {
779778
ty::Clauses<'tcx> : mk_clauses,
780779
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
781780
&'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
782-
CanonicalVarInfos<'tcx> : mk_canonical_var_infos,
783781
}

compiler/rustc_middle/src/ty/typeck_results.rs

+2
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ pub type CanonicalUserTypeAnnotations<'tcx> =
716716

717717
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
718718
pub struct CanonicalUserTypeAnnotation<'tcx> {
719+
#[type_foldable(identity)]
720+
#[type_visitable(ignore)]
719721
pub user_ty: Box<CanonicalUserType<'tcx>>,
720722
pub span: Span,
721723
pub inferred_ty: Ty<'tcx>,

0 commit comments

Comments
 (0)