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 077f081

Browse files
committed
eagerly compute sub_relations again
1 parent 7386636 commit 077f081

File tree

15 files changed

+152
-111
lines changed

15 files changed

+152
-111
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
};
@@ -188,14 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
188187
///
189188
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
190189
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
191-
let mut sub_relations = SubRelations::default();
192-
sub_relations.add_constraints(
193-
self,
194-
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
195-
);
196190
TypeErrCtxt {
197191
infcx: &self.infcx,
198-
sub_relations: RefCell::new(sub_relations),
199192
typeck_results: Some(self.typeck_results.borrow()),
200193
fallback_has_occurred: self.fallback_has_occurred.get(),
201194
normalize_fn_sig: Box::new(|fn_sig| {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
179179
self.inner.borrow_mut().type_variables().equate(a, b);
180180
}
181181

182+
fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
183+
self.sub_ty_vids_raw(a, b);
184+
}
185+
182186
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
183187
self.inner.borrow_mut().int_unification_table().union(a, b);
184188
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,7 @@ impl<'tcx> InferCtxt<'tcx> {
764764
let r_b = self.shallow_resolve(predicate.skip_binder().b);
765765
match (r_a.kind(), r_b.kind()) {
766766
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
767+
self.sub_ty_vids_raw(a_vid, b_vid);
767768
return Err((a_vid, b_vid));
768769
}
769770
_ => {}
@@ -1124,6 +1125,14 @@ impl<'tcx> InferCtxt<'tcx> {
11241125
self.inner.borrow_mut().type_variables().root_var(var)
11251126
}
11261127

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

‎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

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

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,48 @@ use tracing::debug;
1313

1414
use crate::infer::InferCtxtUndoLogs;
1515

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<TyVidSubKey>>),
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<TyVidSubKey>>> for UndoLog<'tcx> {
32+
fn from(l: sv::UndoLog<ut::Delegate<TyVidSubKey>>) -> Self {
33+
UndoLog::SubRelation(l)
34+
}
35+
}
36+
1637
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
1738
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
1839
self.eq_relations.reverse(undo)
1940
}
2041
}
2142

43+
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidSubKey>>> for TypeVariableStorage<'tcx> {
44+
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidSubKey>>) {
45+
self.sub_relations.reverse(undo)
46+
}
47+
}
48+
49+
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
50+
fn reverse(&mut self, undo: UndoLog<'tcx>) {
51+
match undo {
52+
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
53+
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
54+
}
55+
}
56+
}
57+
2258
#[derive(Clone, Default)]
2359
pub(crate) struct TypeVariableStorage<'tcx> {
2460
/// The origins of each type variable.
@@ -27,6 +63,23 @@ pub(crate) struct TypeVariableStorage<'tcx> {
2763
/// constraint `?X == ?Y`. This table also stores, for each key,
2864
/// the known value.
2965
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
66+
/// Only used by `-Znext-solver` and for diagnostics.
67+
///
68+
/// When reporting ambiguity errors, we sometimes want to
69+
/// treat all inference vars which are subtypes of each
70+
/// others as if they are equal. For this case we compute
71+
/// the transitive closure of our subtype obligations here.
72+
///
73+
/// E.g. when encountering ambiguity errors, we want to suggest
74+
/// specifying some method argument or to add a type annotation
75+
/// to a local variable. Because subtyping cannot change the
76+
/// shape of a type, it's fine if the cause of the ambiguity error
77+
/// is only related to the suggested variable via subtyping.
78+
///
79+
/// Even for something like `let x = returns_arg(); x.method();` the
80+
/// type of `x` is only a supertype of the argument of `returns_arg`. We
81+
/// still want to suggest specifying the type of the argument.
82+
sub_relations: ut::UnificationTableStorage<TyVidSubKey>,
3083
}
3184

3285
pub(crate) struct TypeVariableTable<'a, 'tcx> {
@@ -109,6 +162,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
109162
debug_assert!(self.probe(a).is_unknown());
110163
debug_assert!(self.probe(b).is_unknown());
111164
self.eq_relations().union(a, b);
165+
self.sub_relations().union(a, b);
166+
}
167+
168+
/// Records that `a <: b`, depending on `dir`.
169+
///
170+
/// Precondition: neither `a` nor `b` are known.
171+
pub(crate) fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
172+
debug_assert!(self.probe(a).is_unknown());
173+
debug_assert!(self.probe(b).is_unknown());
174+
self.sub_relations().union(a, b);
112175
}
113176

114177
/// Instantiates `vid` with the type `ty`.
@@ -142,6 +205,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
142205
origin: TypeVariableOrigin,
143206
) -> ty::TyVid {
144207
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
208+
209+
let sub_key = self.sub_relations().new_key(());
210+
debug_assert_eq!(eq_key.vid, sub_key.vid);
211+
145212
let index = self.storage.values.push(TypeVariableData { origin });
146213
debug_assert_eq!(eq_key.vid, index);
147214

@@ -164,6 +231,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
164231
self.eq_relations().find(vid).vid
165232
}
166233

234+
/// Returns the "root" variable of `vid` in the `sub_relations`
235+
/// equivalence table. All type variables that have been are
236+
/// related via equality or subtyping will yield the same root
237+
/// variable (per the union-find algorithm), so `sub_root_var(a)
238+
/// == sub_root_var(b)` implies that:
239+
/// ```text
240+
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
241+
/// ```
242+
pub(crate) fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
243+
self.sub_relations().find(vid).vid
244+
}
245+
167246
/// Retrieves the type to which `vid` has been instantiated, if
168247
/// any.
169248
pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
@@ -181,6 +260,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
181260
self.storage.eq_relations.with_log(self.undo_log)
182261
}
183262

263+
#[inline]
264+
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> {
265+
self.storage.sub_relations.with_log(self.undo_log)
266+
}
267+
184268
/// Returns a range of the type variables created during the snapshot.
185269
pub(crate) fn vars_since_snapshot(
186270
&mut self,
@@ -243,6 +327,33 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
243327
}
244328
}
245329

330+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
331+
pub(crate) struct TyVidSubKey {
332+
vid: ty::TyVid,
333+
}
334+
335+
impl From<ty::TyVid> for TyVidSubKey {
336+
#[inline] // make this function eligible for inlining - it is quite hot.
337+
fn from(vid: ty::TyVid) -> Self {
338+
TyVidSubKey { vid }
339+
}
340+
}
341+
342+
impl ut::UnifyKey for TyVidSubKey {
343+
type Value = ();
344+
#[inline]
345+
fn index(&self) -> u32 {
346+
self.vid.as_u32()
347+
}
348+
#[inline]
349+
fn from_index(i: u32) -> TyVidSubKey {
350+
TyVidSubKey { vid: ty::TyVid::from_u32(i) }
351+
}
352+
fn tag() -> &'static str {
353+
"TyVidSubKey"
354+
}
355+
}
356+
246357
impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
247358
type Error = ut::NoError;
248359

‎compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,10 @@ where
930930
&& goal.param_env.visit_with(&mut visitor).is_continue()
931931
}
932932

933+
pub(super) fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
934+
self.delegate.sub_ty_vids_raw(a, b)
935+
}
936+
933937
#[instrument(level = "trace", skip(self, param_env), ret)]
934938
pub(super) fn eq<T: Relate<I>>(
935939
&mut self,

‎compiler/rustc_next_trait_solver/src/solve/mod.rs‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,15 @@ where
122122

123123
#[instrument(level = "trace", skip(self))]
124124
fn compute_subtype_goal(&mut self, goal: Goal<I, ty::SubtypePredicate<I>>) -> QueryResult<I> {
125-
if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
126-
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
127-
} else {
128-
self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
129-
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
125+
match (goal.predicate.a.kind(), goal.predicate.b.kind()) {
126+
(ty::Infer(ty::TyVar(a_vid)), ty::Infer(ty::TyVar(b_vid))) => {
127+
self.sub_ty_vids_raw(a_vid, b_vid);
128+
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
129+
}
130+
_ => {
131+
self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
132+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
133+
}
130134
}
131135
}
132136

‎compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ mod suggest;
9191
pub mod need_type_info;
9292
pub mod nice_region_error;
9393
pub mod region;
94-
pub mod sub_relations;
9594

9695
/// Makes a valid string literal from a string by escaping special characters (" and \),
9796
/// unless they are already escaped.

‎compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
894894
use ty::{Infer, TyVar};
895895
match (inner_ty.kind(), target_ty.kind()) {
896896
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
897-
self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid,b_vid)
897+
self.tecx.sub_root_var(a_vid) == self.tecx.sub_root_var(b_vid)
898898
}
899899
_ => false,
900900
}

0 commit comments

Comments
(0)

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