]> git.proxmox.com Git - rustc.git/blame - src/librustc_infer/infer/type_variable.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_infer / infer / type_variable.rs
CommitLineData
dfeec247 1use rustc_hir::def_id::DefId;
ba9703b0 2use rustc_middle::ty::{self, Ty, TyVid};
dfeec247
XL
3use rustc_span::symbol::Symbol;
4use rustc_span::Span;
c1a9b12d 5
f9f354fc
XL
6use crate::infer::InferCtxtUndoLogs;
7
dfeec247
XL
8use rustc_data_structures::snapshot_vec as sv;
9use rustc_data_structures::unify as ut;
0531ce1d 10use std::cmp;
85aaf69f 11use std::marker::PhantomData;
532ac7d7 12use std::ops::Range;
1a4d82fc 13
f9f354fc
XL
14use rustc_data_structures::undo_log::{Rollback, UndoLogs};
15
16/// Represents a single undo-able action that affects a type inference variable.
17pub(crate) enum UndoLog<'tcx> {
18 EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
19 SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
20 Values(sv::UndoLog<Delegate>),
21}
22
23/// Convert from a specific kind of undo to the more general UndoLog
24impl<'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
31impl<'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/// Convert from a specific kind of undo to the more general UndoLog
38impl<'tcx> From<sv::UndoLog<Delegate>> for UndoLog<'tcx> {
39 fn from(l: sv::UndoLog<Delegate>) -> Self {
40 UndoLog::Values(l)
41 }
42}
43
44/// Convert from a specific kind of undo to the more general UndoLog
45impl<'tcx> From<Instantiate> for UndoLog<'tcx> {
46 fn from(l: Instantiate) -> Self {
47 UndoLog::Values(sv::UndoLog::Other(l))
48 }
49}
50
51impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
52 fn reverse(&mut self, undo: UndoLog<'tcx>) {
53 match undo {
54 UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
55 UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
56 UndoLog::Values(undo) => self.values.reverse(undo),
57 }
58 }
59}
60
61pub struct TypeVariableStorage<'tcx> {
62 values: sv::SnapshotVecStorage<Delegate>,
cc61c64b
XL
63
64 /// Two variables are unified in `eq_relations` when we have a
0531ce1d
XL
65 /// constraint `?X == ?Y`. This table also stores, for each key,
66 /// the known value.
f9f354fc 67 eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
cc61c64b 68
48663c56 69 /// Two variables are unified in `sub_relations` when we have a
cc61c64b
XL
70 /// constraint `?X <: ?Y` *or* a constraint `?Y <: ?X`. This second
71 /// table exists only to help with the occurs check. In particular,
72 /// we want to report constraints like these as an occurs check
73 /// violation:
74 ///
75 /// ?1 <: ?3
76 /// Box<?3> <: ?1
77 ///
78 /// This works because `?1` and `?3` are unified in the
79 /// `sub_relations` relation (not in `eq_relations`). Then when we
80 /// process the `Box<?3> <: ?1` constraint, we do an occurs check
81 /// on `Box<?3>` and find a potential cycle.
82 ///
83 /// This is reasonable because, in Rust, subtypes have the same
84 /// "skeleton" and hence there is no possible type such that
85 /// (e.g.) `Box<?3> <: ?3` for any `?3`.
f9f354fc
XL
86 sub_relations: ut::UnificationTableStorage<ty::TyVid>,
87}
88
89pub struct TypeVariableTable<'a, 'tcx> {
90 storage: &'a mut TypeVariableStorage<'tcx>,
91
92 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
1a4d82fc
JJ
93}
94
dc9dc135
XL
95#[derive(Copy, Clone, Debug)]
96pub struct TypeVariableOrigin {
97 pub kind: TypeVariableOriginKind,
98 pub span: Span,
99}
100
476ff2be 101/// Reasons to create a type inference variable
cc61c64b 102#[derive(Copy, Clone, Debug)]
dc9dc135
XL
103pub enum TypeVariableOriginKind {
104 MiscVariable,
105 NormalizeProjectionType,
106 TypeInference,
dfeec247 107 TypeParameterDefinition(Symbol, Option<DefId>),
ff7c6d11 108
dc9dc135
XL
109 /// One of the upvars or closure kind parameters in a `ClosureSubsts`
110 /// (before it has been determined).
ba9703b0 111 // FIXME(eddyb) distinguish upvar inference variables from the rest.
dc9dc135
XL
112 ClosureSynthetic,
113 SubstitutionPlaceholder,
114 AutoDeref,
115 AdjustmentType,
116 DivergingFn,
117 LatticeVariable,
476ff2be
SL
118}
119
f9f354fc 120pub(crate) struct TypeVariableData {
476ff2be 121 origin: TypeVariableOrigin,
a1dfa0c6 122 diverging: bool,
1a4d82fc
JJ
123}
124
0531ce1d
XL
125#[derive(Copy, Clone, Debug)]
126pub enum TypeVariableValue<'tcx> {
127 Known { value: Ty<'tcx> },
83c7162d 128 Unknown { universe: ty::UniverseIndex },
c1a9b12d
SL
129}
130
0531ce1d 131impl<'tcx> TypeVariableValue<'tcx> {
83c7162d
XL
132 /// If this value is known, returns the type it is known to be.
133 /// Otherwise, `None`.
0531ce1d
XL
134 pub fn known(&self) -> Option<Ty<'tcx>> {
135 match *self {
136 TypeVariableValue::Unknown { .. } => None,
137 TypeVariableValue::Known { value } => Some(value),
138 }
139 }
140
141 pub fn is_unknown(&self) -> bool {
142 match *self {
143 TypeVariableValue::Unknown { .. } => true,
144 TypeVariableValue::Known { .. } => false,
145 }
146 }
1a4d82fc
JJ
147}
148
f9f354fc 149pub(crate) struct Instantiate {
cc61c64b 150 vid: ty::TyVid,
1a4d82fc
JJ
151}
152
f9f354fc 153pub(crate) struct Delegate;
1a4d82fc 154
f9f354fc
XL
155impl<'tcx> TypeVariableStorage<'tcx> {
156 pub fn new() -> TypeVariableStorage<'tcx> {
157 TypeVariableStorage {
158 values: sv::SnapshotVecStorage::new(),
159 eq_relations: ut::UnificationTableStorage::new(),
160 sub_relations: ut::UnificationTableStorage::new(),
54a0048b 161 }
1a4d82fc
JJ
162 }
163
f9f354fc
XL
164 #[inline]
165 pub(crate) fn with_log<'a>(
166 &'a mut self,
167 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
168 ) -> TypeVariableTable<'a, 'tcx> {
169 TypeVariableTable { storage: self, undo_log }
170 }
171}
172
173impl<'tcx> TypeVariableTable<'_, 'tcx> {
0531ce1d
XL
174 /// Returns the diverges flag given when `vid` was created.
175 ///
176 /// Note that this function does not return care whether
177 /// `vid` has been unified with something else or not.
416331ca 178 pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
f9f354fc 179 self.storage.values.get(vid.index as usize).diverging
1a4d82fc
JJ
180 }
181
0531ce1d
XL
182 /// Returns the origin that was given when `vid` was created.
183 ///
184 /// Note that this function does not return care whether
185 /// `vid` has been unified with something else or not.
476ff2be 186 pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
f9f354fc 187 &self.storage.values.get(vid.index as usize).origin
476ff2be
SL
188 }
189
cc61c64b 190 /// Records that `a == b`, depending on `dir`.
1a4d82fc
JJ
191 ///
192 /// Precondition: neither `a` nor `b` are known.
cc61c64b 193 pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
0531ce1d
XL
194 debug_assert!(self.probe(a).is_unknown());
195 debug_assert!(self.probe(b).is_unknown());
f9f354fc
XL
196 self.eq_relations().union(a, b);
197 self.sub_relations().union(a, b);
1a4d82fc
JJ
198 }
199
cc61c64b 200 /// Records that `a <: b`, depending on `dir`.
54a0048b 201 ///
cc61c64b
XL
202 /// Precondition: neither `a` nor `b` are known.
203 pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
0531ce1d
XL
204 debug_assert!(self.probe(a).is_unknown());
205 debug_assert!(self.probe(b).is_unknown());
f9f354fc 206 self.sub_relations().union(a, b);
cc61c64b
XL
207 }
208
209 /// Instantiates `vid` with the type `ty`.
210 ///
211 /// Precondition: `vid` must not have been previously instantiated.
212 pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
213 let vid = self.root_var(vid);
0531ce1d 214 debug_assert!(self.probe(vid).is_unknown());
dfeec247 215 debug_assert!(
f9f354fc 216 self.eq_relations().probe_value(vid).is_unknown(),
dfeec247
XL
217 "instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
218 vid,
219 ty,
f9f354fc 220 self.eq_relations().probe_value(vid)
dfeec247 221 );
f9f354fc 222 self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
0531ce1d
XL
223
224 // Hack: we only need this so that `types_escaping_snapshot`
225 // can see what has been unified; see the Delegate impl for
226 // more details.
f9f354fc 227 self.undo_log.push(Instantiate { vid });
1a4d82fc
JJ
228 }
229
0531ce1d
XL
230 /// Creates a new type variable.
231 ///
232 /// - `diverging`: indicates if this is a "diverging" type
0731742a 233 /// variable, e.g., one created as the type of a `return`
0531ce1d
XL
234 /// expression. The code in this module doesn't care if a
235 /// variable is diverging, but the main Rust type-checker will
236 /// sometimes "unify" such variables with the `!` or `()` types.
237 /// - `origin`: indicates *why* the type variable was created.
238 /// The code in this module doesn't care, but it can be useful
239 /// for improving error messages.
dfeec247
XL
240 pub fn new_var(
241 &mut self,
242 universe: ty::UniverseIndex,
243 diverging: bool,
244 origin: TypeVariableOrigin,
245 ) -> ty::TyVid {
f9f354fc 246 let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
0531ce1d 247
f9f354fc 248 let sub_key = self.sub_relations().new_key(());
0531ce1d
XL
249 assert_eq!(eq_key.vid, sub_key);
250
f9f354fc 251 let index = self.values().push(TypeVariableData { origin, diverging });
0531ce1d
XL
252 assert_eq!(eq_key.vid.index, index as u32);
253
9fa01778
XL
254 debug!(
255 "new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}",
dfeec247 256 eq_key.vid, universe, diverging, origin,
9fa01778 257 );
0531ce1d
XL
258
259 eq_key.vid
1a4d82fc
JJ
260 }
261
0531ce1d 262 /// Returns the number of type variables created thus far.
476ff2be 263 pub fn num_vars(&self) -> usize {
f9f354fc 264 self.storage.values.len()
476ff2be
SL
265 }
266
cc61c64b
XL
267 /// Returns the "root" variable of `vid` in the `eq_relations`
268 /// equivalence table. All type variables that have been equated
269 /// will yield the same root variable (per the union-find
270 /// algorithm), so `root_var(a) == root_var(b)` implies that `a ==
271 /// b` (transitively).
54a0048b 272 pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
f9f354fc 273 self.eq_relations().find(vid).vid
54a0048b
SL
274 }
275
cc61c64b
XL
276 /// Returns the "root" variable of `vid` in the `sub_relations`
277 /// equivalence table. All type variables that have been are
278 /// related via equality or subtyping will yield the same root
279 /// variable (per the union-find algorithm), so `sub_root_var(a)
280 /// == sub_root_var(b)` implies that:
281 ///
282 /// exists X. (a <: X || X <: a) && (b <: X || X <: b)
283 pub fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
f9f354fc 284 self.sub_relations().find(vid)
cc61c64b
XL
285 }
286
9fa01778 287 /// Returns `true` if `a` and `b` have same "sub-root" (i.e., exists some
cc61c64b
XL
288 /// type X such that `forall i in {a, b}. (i <: X || X <: i)`.
289 pub fn sub_unified(&mut self, a: ty::TyVid, b: ty::TyVid) -> bool {
290 self.sub_root_var(a) == self.sub_root_var(b)
291 }
292
0531ce1d
XL
293 /// Retrieves the type to which `vid` has been instantiated, if
294 /// any.
295 pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
e74abb32
XL
296 self.inlined_probe(vid)
297 }
298
299 /// An always-inlined variant of `probe`, for very hot call sites.
300 #[inline(always)]
301 pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
f9f354fc 302 self.eq_relations().inlined_probe_value(vid)
1a4d82fc
JJ
303 }
304
0531ce1d
XL
305 /// If `t` is a type-inference variable, and it has been
306 /// instantiated, then return the with which it was
307 /// instantiated. Otherwise, returns `t`.
54a0048b 308 pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
e74abb32 309 match t.kind {
dfeec247
XL
310 ty::Infer(ty::TyVar(v)) => match self.probe(v) {
311 TypeVariableValue::Unknown { .. } => t,
312 TypeVariableValue::Known { value } => value,
313 },
1a4d82fc
JJ
314 _ => t,
315 }
316 }
317
f9f354fc
XL
318 #[inline]
319 fn values(
320 &mut self,
321 ) -> sv::SnapshotVec<Delegate, &mut Vec<TypeVariableData>, &mut InferCtxtUndoLogs<'tcx>> {
322 self.storage.values.with_log(self.undo_log)
1a4d82fc
JJ
323 }
324
f9f354fc
XL
325 #[inline]
326 fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> {
327 self.storage.eq_relations.with_log(self.undo_log)
1a4d82fc
JJ
328 }
329
f9f354fc
XL
330 #[inline]
331 fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, ty::TyVid> {
332 self.storage.sub_relations.with_log(self.undo_log)
cc61c64b
XL
333 }
334
532ac7d7
XL
335 /// Returns a range of the type variables created during the snapshot.
336 pub fn vars_since_snapshot(
337 &mut self,
f9f354fc 338 value_count: usize,
532ac7d7 339 ) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
f9f354fc 340 let range = TyVid { index: value_count as u32 }..TyVid { index: self.num_vars() as u32 };
dfeec247 341 (
f9f354fc
XL
342 range.start..range.end,
343 (range.start.index..range.end.index)
344 .map(|index| self.storage.values.get(index as usize).origin)
dfeec247
XL
345 .collect(),
346 )
1a4d82fc
JJ
347 }
348
9fa01778 349 /// Finds the set of type variables that existed *before* `s`
0531ce1d
XL
350 /// but which have only been unified since `s` started, and
351 /// return the types with which they were unified. So if we had
352 /// a type variable `V0`, then we started the snapshot, then we
a1dfa0c6 353 /// created a type variable `V1`, unified `V0` with `T0`, and
0531ce1d 354 /// unified `V1` with `T1`, this function would return `{T0}`.
f9f354fc 355 pub fn types_escaping_snapshot(&mut self, s: &super::Snapshot<'tcx>) -> Vec<Ty<'tcx>> {
1a4d82fc
JJ
356 let mut new_elem_threshold = u32::MAX;
357 let mut escaping_types = Vec::new();
f9f354fc 358 let actions_since_snapshot = self.undo_log.actions_since_snapshot(s);
1a4d82fc 359 debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len());
f9f354fc
XL
360 for i in 0..actions_since_snapshot.len() {
361 let actions_since_snapshot = self.undo_log.actions_since_snapshot(s);
362 match actions_since_snapshot[i] {
363 super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::NewElem(index))) => {
1a4d82fc
JJ
364 // if any new variables were created during the
365 // snapshot, remember the lower index (which will
366 // always be the first one we see). Note that this
367 // action must precede those variables being
368 // specified.
0531ce1d 369 new_elem_threshold = cmp::min(new_elem_threshold, index as u32);
1a4d82fc
JJ
370 debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
371 }
372
f9f354fc
XL
373 super::UndoLog::TypeVariables(UndoLog::Values(sv::UndoLog::Other(
374 Instantiate { vid, .. },
375 ))) => {
1a4d82fc
JJ
376 if vid.index < new_elem_threshold {
377 // quick check to see if this variable was
378 // created since the snapshot started or not.
f9f354fc
XL
379 let mut eq_relations = ut::UnificationTable::with_log(
380 &mut self.storage.eq_relations,
381 &mut *self.undo_log,
382 );
383 let escaping_type = match eq_relations.probe_value(vid) {
0531ce1d
XL
384 TypeVariableValue::Unknown { .. } => bug!(),
385 TypeVariableValue::Known { value } => value,
54a0048b 386 };
1a4d82fc
JJ
387 escaping_types.push(escaping_type);
388 }
389 debug!("SpecifyVar({:?}) new_elem_threshold={}", vid, new_elem_threshold);
390 }
391
dfeec247 392 _ => {}
1a4d82fc
JJ
393 }
394 }
395
396 escaping_types
397 }
c1a9b12d 398
0531ce1d
XL
399 /// Returns indices of all variables that are not yet
400 /// instantiated.
54a0048b 401 pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
f9f354fc 402 (0..self.storage.values.len())
54a0048b
SL
403 .filter_map(|i| {
404 let vid = ty::TyVid { index: i as u32 };
0531ce1d
XL
405 match self.probe(vid) {
406 TypeVariableValue::Unknown { .. } => Some(vid),
407 TypeVariableValue::Known { .. } => None,
54a0048b 408 }
c1a9b12d
SL
409 })
410 .collect()
411 }
1a4d82fc
JJ
412}
413
0531ce1d
XL
414impl sv::SnapshotVecDelegate for Delegate {
415 type Value = TypeVariableData;
416 type Undo = Instantiate;
417
418 fn reverse(_values: &mut Vec<TypeVariableData>, _action: Instantiate) {
419 // We don't actually have to *do* anything to reverse an
48663c56 420 // instantiation; the value for a variable is stored in the
0531ce1d
XL
421 // `eq_relations` and hence its rollback code will handle
422 // it. In fact, we could *almost* just remove the
423 // `SnapshotVec` entirely, except that we would have to
424 // reproduce *some* of its logic, since we want to know which
425 // type variables have been instantiated since the snapshot
426 // was started, so we can implement `types_escaping_snapshot`.
427 //
428 // (If we extended the `UnificationTable` to let us see which
429 // values have been unified and so forth, that might also
430 // suffice.)
431 }
432}
433
434///////////////////////////////////////////////////////////////////////////
435
436/// These structs (a newtyped TyVid) are used as the unification key
437/// for the `eq_relations`; they carry a `TypeVariableValue` along
438/// with them.
439#[derive(Copy, Clone, Debug, PartialEq, Eq)]
f9f354fc 440pub(crate) struct TyVidEqKey<'tcx> {
0531ce1d
XL
441 vid: ty::TyVid,
442
443 // in the table, we map each ty-vid to one of these:
444 phantom: PhantomData<TypeVariableValue<'tcx>>,
445}
446
447impl<'tcx> From<ty::TyVid> for TyVidEqKey<'tcx> {
448 fn from(vid: ty::TyVid) -> Self {
449 TyVidEqKey { vid, phantom: PhantomData }
450 }
451}
452
453impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
454 type Value = TypeVariableValue<'tcx>;
dfeec247
XL
455 fn index(&self) -> u32 {
456 self.vid.index
457 }
458 fn from_index(i: u32) -> Self {
459 TyVidEqKey::from(ty::TyVid { index: i })
460 }
461 fn tag() -> &'static str {
462 "TyVidEqKey"
463 }
0531ce1d
XL
464}
465
466impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
467 type Error = ut::NoError;
468
469 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, ut::NoError> {
470 match (value1, value2) {
471 // We never equate two type variables, both of which
472 // have known types. Instead, we recursively equate
473 // those types.
474 (&TypeVariableValue::Known { .. }, &TypeVariableValue::Known { .. }) => {
475 bug!("equating two type variables, both of which have known types")
476 }
477
478 // If one side is known, prefer that one.
479 (&TypeVariableValue::Known { .. }, &TypeVariableValue::Unknown { .. }) => Ok(*value1),
480 (&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),
1a4d82fc 481
0531ce1d 482 // If both sides are *unknown*, it hardly matters, does it?
dfeec247
XL
483 (
484 &TypeVariableValue::Unknown { universe: universe1 },
485 &TypeVariableValue::Unknown { universe: universe2 },
486 ) => {
83c7162d
XL
487 // If we unify two unbound variables, ?T and ?U, then whatever
488 // value they wind up taking (which must be the same value) must
489 // be nameable by both universes. Therefore, the resulting
490 // universe is the minimum of the two universes, because that is
491 // the one which contains the fewest names in scope.
492 let universe = cmp::min(universe1, universe2);
493 Ok(TypeVariableValue::Unknown { universe })
494 }
0531ce1d 495 }
1a4d82fc
JJ
496 }
497}