Skip to content

Commit 5f5d248

Browse files
committed
Auto merge of #118742 - lcnr:infer-var-cleanup, r=compiler-errors
refactor infer var storage cleanup the code, discovered while working on #118725
2 parents e2a3c9b + 9297826 commit 5f5d248

File tree

7 files changed

+51
-106
lines changed

7 files changed

+51
-106
lines changed

compiler/rustc_hir_typeck/src/fallback.rs

+18-17
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
2424
self.fulfillment_cx.borrow_mut().pending_obligations()
2525
);
2626

27-
let fallback_occured = self.fallback_types() | self.fallback_effects();
27+
let fallback_occurred = self.fallback_types() | self.fallback_effects();
2828

29-
if !fallback_occured {
29+
if !fallback_occurred {
3030
return;
3131
}
3232

@@ -57,24 +57,25 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
5757
}
5858

5959
fn fallback_types(&self) -> bool {
60-
// Check if we have any unsolved variables. If not, no need for fallback.
61-
let unsolved_variables = self.unsolved_variables();
60+
// Check if we have any unresolved variables. If not, no need for fallback.
61+
let unresolved_variables = self.unresolved_variables();
6262

63-
if unsolved_variables.is_empty() {
63+
if unresolved_variables.is_empty() {
6464
return false;
6565
}
6666

67-
let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
67+
let diverging_fallback = self.calculate_diverging_fallback(&unresolved_variables);
6868

6969
// We do fallback in two passes, to try to generate
7070
// better error messages.
7171
// The first time, we do *not* replace opaque types.
72-
for ty in unsolved_variables {
72+
let mut fallback_occurred = false;
73+
for ty in unresolved_variables {
7374
debug!("unsolved_variable = {:?}", ty);
74-
self.fallback_if_possible(ty, &diverging_fallback);
75+
fallback_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
7576
}
7677

77-
true
78+
fallback_occurred
7879
}
7980

8081
fn fallback_effects(&self) -> bool {
@@ -84,9 +85,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
8485
return false;
8586
}
8687

87-
// not setting `fallback_has_occured` here because that field is only used for type fallback
88-
// diagnostics.
89-
88+
// not setting the `fallback_has_occured` field here because
89+
// that field is only used for type fallback diagnostics.
9090
for effect in unsolved_effects {
9191
let expected = self.tcx.consts.true_;
9292
let cause = self.misc(rustc_span::DUMMY_SP);
@@ -122,7 +122,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
122122
&self,
123123
ty: Ty<'tcx>,
124124
diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
125-
) {
125+
) -> bool {
126126
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
127127
// is an unsolved variable, and we determine its fallback
128128
// based solely on how it was created, not what other type
@@ -147,7 +147,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
147147
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
148148
_ => match diverging_fallback.get(&ty) {
149149
Some(&fallback_ty) => fallback_ty,
150-
None => return,
150+
None => return false,
151151
},
152152
};
153153
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
@@ -159,6 +159,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
159159
.unwrap_or(rustc_span::DUMMY_SP);
160160
self.demand_eqtype(span, ty, fallback);
161161
self.fallback_has_occurred.set(true);
162+
true
162163
}
163164

164165
/// The "diverging fallback" system is rather complicated. This is
@@ -230,17 +231,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
230231
/// any variable that has an edge into `D`.
231232
fn calculate_diverging_fallback(
232233
&self,
233-
unsolved_variables: &[Ty<'tcx>],
234+
unresolved_variables: &[Ty<'tcx>],
234235
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
235-
debug!("calculate_diverging_fallback({:?})", unsolved_variables);
236+
debug!("calculate_diverging_fallback({:?})", unresolved_variables);
236237

237238
// Construct a coercion graph where an edge `A -> B` indicates
238239
// a type variable is that is coerced
239240
let coercion_graph = self.create_coercion_graph();
240241

241242
// Extract the unsolved type inference variable vids; note that some
242243
// unsolved variables are integer/float variables and are excluded.
243-
let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
244+
let unsolved_vids = unresolved_variables.iter().filter_map(|ty| ty.ty_vid());
244245

245246
// Compute the diverging root vids D -- that is, the root vid of
246247
// those type variables that (a) are the target of a coercion from

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

+1-4
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,7 @@ impl<'tcx> InferCtxt<'tcx> {
166166
}
167167

168168
fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
169-
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
170-
.into_iter()
171-
.map(|(k, v)| (k, v.hidden_type.ty))
172-
.collect()
169+
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.hidden_type.ty)).collect()
173170
}
174171

175172
/// Given the (canonicalized) result to a canonical query,

compiler/rustc_infer/src/infer/generalize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ where
295295
ty::Covariant | ty::Contravariant => (),
296296
}
297297

298-
let origin = *inner.type_variables().var_origin(vid);
298+
let origin = inner.type_variables().var_origin(vid);
299299
let new_var_id =
300300
inner.type_variables().new_var(self.for_universe, origin);
301301
let u = Ty::new_var(self.tcx(), new_var_id);

compiler/rustc_infer/src/infer/mod.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
9898
/// call to `start_snapshot` and `rollback_to`.
9999
#[derive(Clone)]
100100
pub struct InferCtxtInner<'tcx> {
101+
undo_log: InferCtxtUndoLogs<'tcx>,
102+
101103
/// Cache for projections.
102104
///
103105
/// This cache is snapshotted along with the infcx.
@@ -162,18 +164,17 @@ pub struct InferCtxtInner<'tcx> {
162164
/// that all type inference variables have been bound and so forth.
163165
region_obligations: Vec<RegionObligation<'tcx>>,
164166

165-
undo_log: InferCtxtUndoLogs<'tcx>,
166-
167167
/// Caches for opaque type inference.
168168
opaque_type_storage: OpaqueTypeStorage<'tcx>,
169169
}
170170

171171
impl<'tcx> InferCtxtInner<'tcx> {
172172
fn new() -> InferCtxtInner<'tcx> {
173173
InferCtxtInner {
174+
undo_log: InferCtxtUndoLogs::default(),
175+
174176
projection_cache: Default::default(),
175177
type_variable_storage: type_variable::TypeVariableStorage::new(),
176-
undo_log: InferCtxtUndoLogs::default(),
177178
const_unification_storage: ut::UnificationTableStorage::new(),
178179
int_unification_storage: ut::UnificationTableStorage::new(),
179180
float_unification_storage: ut::UnificationTableStorage::new(),
@@ -783,7 +784,7 @@ impl<'tcx> InferCtxt<'tcx> {
783784
pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
784785
match *ty.kind() {
785786
ty::Infer(ty::TyVar(vid)) => {
786-
Some(*self.inner.borrow_mut().type_variables().var_origin(vid))
787+
Some(self.inner.borrow_mut().type_variables().var_origin(vid))
787788
}
788789
_ => None,
789790
}
@@ -793,11 +794,11 @@ impl<'tcx> InferCtxt<'tcx> {
793794
freshen::TypeFreshener::new(self)
794795
}
795796

796-
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
797+
pub fn unresolved_variables(&self) -> Vec<Ty<'tcx>> {
797798
let mut inner = self.inner.borrow_mut();
798799
let mut vars: Vec<Ty<'_>> = inner
799800
.type_variables()
800-
.unsolved_variables()
801+
.unresolved_variables()
801802
.into_iter()
802803
.map(|t| Ty::new_var(self.tcx, t))
803804
.collect();
@@ -1306,12 +1307,7 @@ impl<'tcx> InferCtxt<'tcx> {
13061307
pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
13071308
let mut inner = self.inner.borrow_mut();
13081309
let inner = &mut *inner;
1309-
inner
1310-
.region_constraint_storage
1311-
.as_mut()
1312-
.expect("regions already resolved")
1313-
.with_log(&mut inner.undo_log)
1314-
.var_origin(vid)
1310+
inner.unwrap_region_constraints().var_origin(vid)
13151311
}
13161312

13171313
/// Clone the list of variable regions. This is used only during NLL processing

compiler/rustc_infer/src/infer/resolve.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for UnresolvedTypeOrConstFinder<'a, 'tc
134134
if let TypeVariableOrigin {
135135
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
136136
span,
137-
} = *ty_vars.var_origin(ty_vid)
137+
} = ty_vars.var_origin(ty_vid)
138138
{
139139
Some(span)
140140
} else {

compiler/rustc_infer/src/infer/type_variable.rs

+19-68
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_hir::def_id::DefId;
2+
use rustc_index::IndexVec;
23
use rustc_middle::ty::{self, Ty, TyVid};
34
use rustc_span::symbol::Symbol;
45
use rustc_span::Span;
@@ -11,14 +12,13 @@ use std::cmp;
1112
use std::marker::PhantomData;
1213
use std::ops::Range;
1314

14-
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
15+
use rustc_data_structures::undo_log::Rollback;
1516

1617
/// Represents a single undo-able action that affects a type inference variable.
1718
#[derive(Clone)]
1819
pub(crate) enum UndoLog<'tcx> {
1920
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
2021
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
21-
Values(sv::UndoLog<Delegate>),
2222
}
2323

2424
/// Convert from a specific kind of undo to the more general UndoLog
@@ -35,34 +35,19 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
3535
}
3636
}
3737

38-
/// Convert from a specific kind of undo to the more general UndoLog
39-
impl<'tcx> From<sv::UndoLog<Delegate>> for UndoLog<'tcx> {
40-
fn from(l: sv::UndoLog<Delegate>) -> Self {
41-
UndoLog::Values(l)
42-
}
43-
}
44-
45-
/// Convert from a specific kind of undo to the more general UndoLog
46-
impl<'tcx> From<Instantiate> for UndoLog<'tcx> {
47-
fn from(l: Instantiate) -> Self {
48-
UndoLog::Values(sv::UndoLog::Other(l))
49-
}
50-
}
51-
5238
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
5339
fn reverse(&mut self, undo: UndoLog<'tcx>) {
5440
match undo {
5541
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
5642
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
57-
UndoLog::Values(undo) => self.values.reverse(undo),
5843
}
5944
}
6045
}
6146

6247
#[derive(Clone)]
6348
pub struct TypeVariableStorage<'tcx> {
64-
values: sv::SnapshotVecStorage<Delegate>,
65-
49+
/// The origins of each type variable.
50+
values: IndexVec<TyVid, TypeVariableData>,
6651
/// Two variables are unified in `eq_relations` when we have a
6752
/// constraint `?X == ?Y`. This table also stores, for each key,
6853
/// the known value.
@@ -168,15 +153,10 @@ impl<'tcx> TypeVariableValue<'tcx> {
168153
}
169154
}
170155

171-
#[derive(Clone)]
172-
pub(crate) struct Instantiate;
173-
174-
pub(crate) struct Delegate;
175-
176156
impl<'tcx> TypeVariableStorage<'tcx> {
177157
pub fn new() -> TypeVariableStorage<'tcx> {
178158
TypeVariableStorage {
179-
values: sv::SnapshotVecStorage::new(),
159+
values: Default::default(),
180160
eq_relations: ut::UnificationTableStorage::new(),
181161
sub_relations: ut::UnificationTableStorage::new(),
182162
}
@@ -194,15 +174,20 @@ impl<'tcx> TypeVariableStorage<'tcx> {
194174
pub(crate) fn eq_relations_ref(&self) -> &ut::UnificationTableStorage<TyVidEqKey<'tcx>> {
195175
&self.eq_relations
196176
}
177+
178+
pub(super) fn finalize_rollback(&mut self) {
179+
debug_assert!(self.values.len() >= self.eq_relations.len());
180+
self.values.truncate(self.eq_relations.len());
181+
}
197182
}
198183

199184
impl<'tcx> TypeVariableTable<'_, 'tcx> {
200185
/// Returns the origin that was given when `vid` was created.
201186
///
202187
/// Note that this function does not return care whether
203188
/// `vid` has been unified with something else or not.
204-
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
205-
&self.storage.values.get(vid.as_usize()).origin
189+
pub fn var_origin(&self, vid: ty::TyVid) -> TypeVariableOrigin {
190+
self.storage.values[vid].origin
206191
}
207192

208193
/// Records that `a == b`, depending on `dir`.
@@ -237,11 +222,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
237222
self.eq_relations().probe_value(vid)
238223
);
239224
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
240-
241-
// Hack: we only need this so that `types_escaping_snapshot`
242-
// can see what has been unified; see the Delegate impl for
243-
// more details.
244-
self.undo_log.push(Instantiate);
245225
}
246226

247227
/// Creates a new type variable.
@@ -262,14 +242,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
262242
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
263243

264244
let sub_key = self.sub_relations().new_key(());
265-
assert_eq!(eq_key.vid, sub_key);
245+
debug_assert_eq!(eq_key.vid, sub_key);
266246

267-
let index = self.values().push(TypeVariableData { origin });
268-
assert_eq!(eq_key.vid.as_u32(), index as u32);
247+
let index = self.storage.values.push(TypeVariableData { origin });
248+
debug_assert_eq!(eq_key.vid, index);
269249

270250
debug!("new_var(index={:?}, universe={:?}, origin={:?})", eq_key.vid, universe, origin);
271251

272-
eq_key.vid
252+
index
273253
}
274254

275255
/// Returns the number of type variables created thus far.
@@ -329,13 +309,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
329309
}
330310
}
331311

332-
#[inline]
333-
fn values(
334-
&mut self,
335-
) -> sv::SnapshotVec<Delegate, &mut Vec<TypeVariableData>, &mut InferCtxtUndoLogs<'tcx>> {
336-
self.storage.values.with_log(self.undo_log)
337-
}
338-
339312
#[inline]
340313
fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> {
341314
self.storage.eq_relations.with_log(self.undo_log)
@@ -354,16 +327,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
354327
let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
355328
(
356329
range.start..range.end,
357-
(range.start.as_usize()..range.end.as_usize())
358-
.map(|index| self.storage.values.get(index).origin)
359-
.collect(),
330+
(range.start..range.end).map(|index| self.var_origin(index)).collect(),
360331
)
361332
}
362333

363334
/// Returns indices of all variables that are not yet
364335
/// instantiated.
365-
pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
366-
(0..self.storage.values.len())
336+
pub fn unresolved_variables(&mut self) -> Vec<ty::TyVid> {
337+
(0..self.num_vars())
367338
.filter_map(|i| {
368339
let vid = ty::TyVid::from_usize(i);
369340
match self.probe(vid) {
@@ -375,26 +346,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
375346
}
376347
}
377348

378-
impl sv::SnapshotVecDelegate for Delegate {
379-
type Value = TypeVariableData;
380-
type Undo = Instantiate;
381-
382-
fn reverse(_values: &mut Vec<TypeVariableData>, _action: Instantiate) {
383-
// We don't actually have to *do* anything to reverse an
384-
// instantiation; the value for a variable is stored in the
385-
// `eq_relations` and hence its rollback code will handle
386-
// it. In fact, we could *almost* just remove the
387-
// `SnapshotVec` entirely, except that we would have to
388-
// reproduce *some* of its logic, since we want to know which
389-
// type variables have been instantiated since the snapshot
390-
// was started, so we can implement `types_escaping_snapshot`.
391-
//
392-
// (If we extended the `UnificationTable` to let us see which
393-
// values have been unified and so forth, that might also
394-
// suffice.)
395-
}
396-
}
397-
398349
///////////////////////////////////////////////////////////////////////////
399350

400351
/// These structs (a newtyped TyVid) are used as the unification key

0 commit comments

Comments
 (0)