]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/region_constraints/mod.rs
f2235fe8d6d1245868a8167a6d83499f05250b40
[rust.git] / src / librustc / infer / region_constraints / mod.rs
1 //! See `README.md`.
2
3 use self::CombineMapType::*;
4 use self::UndoLog::*;
5
6 use super::unify_key;
7 use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
8
9 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
10 use rustc_data_structures::indexed_vec::IndexVec;
11 use rustc_data_structures::unify as ut;
12 use crate::ty::ReStatic;
13 use crate::ty::{self, Ty, TyCtxt};
14 use crate::ty::{ReLateBound, ReVar};
15 use crate::ty::{Region, RegionVid};
16
17 use std::collections::BTreeMap;
18 use std::{cmp, fmt, mem};
19 use std::ops::Range;
20
21 mod leak_check;
22
23 #[derive(Default)]
24 pub struct RegionConstraintCollector<'tcx> {
25     /// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
26     var_infos: IndexVec<RegionVid, RegionVariableInfo>,
27
28     data: RegionConstraintData<'tcx>,
29
30     /// For a given pair of regions (R1, R2), maps to a region R3 that
31     /// is designated as their LUB (edges R1 <= R3 and R2 <= R3
32     /// exist). This prevents us from making many such regions.
33     lubs: CombineMap<'tcx>,
34
35     /// For a given pair of regions (R1, R2), maps to a region R3 that
36     /// is designated as their GLB (edges R3 <= R1 and R3 <= R2
37     /// exist). This prevents us from making many such regions.
38     glbs: CombineMap<'tcx>,
39
40     /// The undo log records actions that might later be undone.
41     ///
42     /// Note: `num_open_snapshots` is used to track if we are actively
43     /// snapshotting. When the `start_snapshot()` method is called, we
44     /// increment `num_open_snapshots` to indicate that we are now actively
45     /// snapshotting. The reason for this is that otherwise we end up adding
46     /// entries for things like the lower bound on a variable and so forth,
47     /// which can never be rolled back.
48     undo_log: Vec<UndoLog<'tcx>>,
49
50     /// The number of open snapshots, i.e., those that haven't been committed or
51     /// rolled back.
52     num_open_snapshots: usize,
53
54     /// When we add a R1 == R2 constriant, we currently add (a) edges
55     /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
56     /// table. You can then call `opportunistic_resolve_var` early
57     /// which will map R1 and R2 to some common region (i.e., either
58     /// R1 or R2). This is important when dropck and other such code
59     /// is iterating to a fixed point, because otherwise we sometimes
60     /// would wind up with a fresh stream of region variables that
61     /// have been equated but appear distinct.
62     unification_table: ut::UnificationTable<ut::InPlace<ty::RegionVid>>,
63
64     /// a flag set to true when we perform any unifications; this is used
65     /// to micro-optimize `take_and_reset_data`
66     any_unifications: bool,
67 }
68
69 pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
70
71 /// The full set of region constraints gathered up by the collector.
72 /// Describes constraints between the region variables and other
73 /// regions, as well as other conditions that must be verified, or
74 /// assumptions that can be made.
75 #[derive(Debug, Default, Clone)]
76 pub struct RegionConstraintData<'tcx> {
77     /// Constraints of the form `A <= B`, where either `A` or `B` can
78     /// be a region variable (or neither, as it happens).
79     pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
80
81     /// A "verify" is something that we need to verify after inference
82     /// is done, but which does not directly affect inference in any
83     /// way.
84     ///
85     /// An example is a `A <= B` where neither `A` nor `B` are
86     /// inference variables.
87     pub verifys: Vec<Verify<'tcx>>,
88
89     /// A "given" is a relationship that is known to hold. In
90     /// particular, we often know from closure fn signatures that a
91     /// particular free region must be a subregion of a region
92     /// variable:
93     ///
94     ///    foo.iter().filter(<'a> |x: &'a &'b T| ...)
95     ///
96     /// In situations like this, `'b` is in fact a region variable
97     /// introduced by the call to `iter()`, and `'a` is a bound region
98     /// on the closure (as indicated by the `<'a>` prefix). If we are
99     /// naive, we wind up inferring that `'b` must be `'static`,
100     /// because we require that it be greater than `'a` and we do not
101     /// know what `'a` is precisely.
102     ///
103     /// This hashmap is used to avoid that naive scenario. Basically
104     /// we record the fact that `'a <= 'b` is implied by the fn
105     /// signature, and then ignore the constraint when solving
106     /// equations. This is a bit of a hack but seems to work.
107     pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>,
108 }
109
110 /// Represents a constraint that influences the inference process.
111 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
112 pub enum Constraint<'tcx> {
113     /// A region variable is a subregion of another.
114     VarSubVar(RegionVid, RegionVid),
115
116     /// A concrete region is a subregion of region variable.
117     RegSubVar(Region<'tcx>, RegionVid),
118
119     /// A region variable is a subregion of a concrete region. This does not
120     /// directly affect inference, but instead is checked after
121     /// inference is complete.
122     VarSubReg(RegionVid, Region<'tcx>),
123
124     /// A constraint where neither side is a variable. This does not
125     /// directly affect inference, but instead is checked after
126     /// inference is complete.
127     RegSubReg(Region<'tcx>, Region<'tcx>),
128 }
129
130 impl Constraint<'_> {
131     pub fn involves_placeholders(&self) -> bool {
132         match self {
133             Constraint::VarSubVar(_, _) => false,
134             Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(),
135             Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(),
136         }
137     }
138 }
139
140 /// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
141 /// associated type) must outlive the region `R`. `T` is known to
142 /// outlive `RS`. Therefore, verify that `R <= RS[i]` for some
143 /// `i`. Inference variables may be involved (but this verification
144 /// step doesn't influence inference).
145 #[derive(Debug, Clone)]
146 pub struct Verify<'tcx> {
147     pub kind: GenericKind<'tcx>,
148     pub origin: SubregionOrigin<'tcx>,
149     pub region: Region<'tcx>,
150     pub bound: VerifyBound<'tcx>,
151 }
152
153 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
154 pub enum GenericKind<'tcx> {
155     Param(ty::ParamTy),
156     Projection(ty::ProjectionTy<'tcx>),
157 }
158
159 EnumTypeFoldableImpl! {
160     impl<'tcx> TypeFoldable<'tcx> for GenericKind<'tcx> {
161         (GenericKind::Param)(a),
162         (GenericKind::Projection)(a),
163     }
164 }
165
166 /// Describes the things that some `GenericKind` value `G` is known to
167 /// outlive. Each variant of `VerifyBound` can be thought of as a
168 /// function:
169 ///
170 ///     fn(min: Region) -> bool { .. }
171 ///
172 /// where `true` means that the region `min` meets that `G: min`.
173 /// (False means nothing.)
174 ///
175 /// So, for example, if we have the type `T` and we have in scope that
176 /// `T: 'a` and `T: 'b`, then the verify bound might be:
177 ///
178 ///     fn(min: Region) -> bool {
179 ///        ('a: min) || ('b: min)
180 ///     }
181 ///
182 /// This is described with a `AnyRegion('a, 'b)` node.
183 #[derive(Debug, Clone)]
184 pub enum VerifyBound<'tcx> {
185     /// Given a kind K and a bound B, expands to a function like the
186     /// following, where `G` is the generic for which this verify
187     /// bound was created:
188     ///
189     /// ```rust
190     /// fn(min) -> bool {
191     ///     if G == K {
192     ///         B(min)
193     ///     } else {
194     ///         false
195     ///     }
196     /// }
197     /// ```
198     ///
199     /// In other words, if the generic `G` that we are checking is
200     /// equal to `K`, then check the associated verify bound
201     /// (otherwise, false).
202     ///
203     /// This is used when we have something in the environment that
204     /// may or may not be relevant, depending on the region inference
205     /// results. For example, we may have `where <T as
206     /// Trait<'a>>::Item: 'b` in our where-clauses. If we are
207     /// generating the verify-bound for `<T as Trait<'0>>::Item`, then
208     /// this where-clause is only relevant if `'0` winds up inferred
209     /// to `'a`.
210     ///
211     /// So we would compile to a verify-bound like
212     ///
213     /// ```
214     /// IfEq(<T as Trait<'a>>::Item, AnyRegion('a))
215     /// ```
216     ///
217     /// meaning, if the subject G is equal to `<T as Trait<'a>>::Item`
218     /// (after inference), and `'a: min`, then `G: min`.
219     IfEq(Ty<'tcx>, Box<VerifyBound<'tcx>>),
220
221     /// Given a region `R`, expands to the function:
222     ///
223     /// ```
224     /// fn(min) -> bool {
225     ///     R: min
226     /// }
227     /// ```
228     ///
229     /// This is used when we can establish that `G: R` -- therefore,
230     /// if `R: min`, then by transitivity `G: min`.
231     OutlivedBy(Region<'tcx>),
232
233     /// Given a set of bounds `B`, expands to the function:
234     ///
235     /// ```rust
236     /// fn(min) -> bool {
237     ///     exists (b in B) { b(min) }
238     /// }
239     /// ```
240     ///
241     /// In other words, if we meet some bound in `B`, that suffices.
242     /// This is used when all the bounds in `B` are known to apply to `G`.
243     AnyBound(Vec<VerifyBound<'tcx>>),
244
245     /// Given a set of bounds `B`, expands to the function:
246     ///
247     /// ```rust
248     /// fn(min) -> bool {
249     ///     forall (b in B) { b(min) }
250     /// }
251     /// ```
252     ///
253     /// In other words, if we meet *all* bounds in `B`, that suffices.
254     /// This is used when *some* bound in `B` is known to suffice, but
255     /// we don't know which.
256     AllBounds(Vec<VerifyBound<'tcx>>),
257 }
258
259 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
260 struct TwoRegions<'tcx> {
261     a: Region<'tcx>,
262     b: Region<'tcx>,
263 }
264
265 #[derive(Copy, Clone, PartialEq)]
266 enum UndoLog<'tcx> {
267     /// We added `RegionVid`.
268     AddVar(RegionVid),
269
270     /// We added the given `constraint`.
271     AddConstraint(Constraint<'tcx>),
272
273     /// We added the given `verify`.
274     AddVerify(usize),
275
276     /// We added the given `given`.
277     AddGiven(Region<'tcx>, ty::RegionVid),
278
279     /// We added a GLB/LUB "combination variable".
280     AddCombination(CombineMapType, TwoRegions<'tcx>),
281
282     /// During skolemization, we sometimes purge entries from the undo
283     /// log in a kind of minisnapshot (unlike other snapshots, this
284     /// purging actually takes place *on success*). In that case, we
285     /// replace the corresponding entry with `Noop` so as to avoid the
286     /// need to do a bunch of swapping. (We can't use `swap_remove` as
287     /// the order of the vector is important.)
288     Purged,
289 }
290
291 #[derive(Copy, Clone, PartialEq)]
292 enum CombineMapType {
293     Lub,
294     Glb,
295 }
296
297 type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
298
299 #[derive(Debug, Clone, Copy)]
300 pub struct RegionVariableInfo {
301     pub origin: RegionVariableOrigin,
302     pub universe: ty::UniverseIndex,
303 }
304
305 pub struct RegionSnapshot {
306     length: usize,
307     region_snapshot: ut::Snapshot<ut::InPlace<ty::RegionVid>>,
308     any_unifications: bool,
309 }
310
311 /// When working with placeholder regions, we often wish to find all of
312 /// the regions that are either reachable from a placeholder region, or
313 /// which can reach a placeholder region, or both. We call such regions
314 /// *tainted* regions. This struct allows you to decide what set of
315 /// tainted regions you want.
316 #[derive(Debug)]
317 pub struct TaintDirections {
318     incoming: bool,
319     outgoing: bool,
320 }
321
322 impl TaintDirections {
323     pub fn incoming() -> Self {
324         TaintDirections {
325             incoming: true,
326             outgoing: false,
327         }
328     }
329
330     pub fn outgoing() -> Self {
331         TaintDirections {
332             incoming: false,
333             outgoing: true,
334         }
335     }
336
337     pub fn both() -> Self {
338         TaintDirections {
339             incoming: true,
340             outgoing: true,
341         }
342     }
343 }
344
345 pub struct ConstraintInfo {}
346
347 impl<'tcx> RegionConstraintCollector<'tcx> {
348     pub fn new() -> Self {
349         Self::default()
350     }
351
352     pub fn num_region_vars(&self) -> usize {
353         self.var_infos.len()
354     }
355
356     pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
357         &self.data
358     }
359
360     /// Once all the constraints have been gathered, extract out the final data.
361     ///
362     /// Not legal during a snapshot.
363     pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
364         assert!(!self.in_snapshot());
365         (self.var_infos, self.data)
366     }
367
368     /// Takes (and clears) the current set of constraints. Note that
369     /// the set of variables remains intact, but all relationships
370     /// between them are reset. This is used during NLL checking to
371     /// grab the set of constraints that arose from a particular
372     /// operation.
373     ///
374     /// We don't want to leak relationships between variables between
375     /// points because just because (say) `r1 == r2` was true at some
376     /// point P in the graph doesn't imply that it will be true at
377     /// some other point Q, in NLL.
378     ///
379     /// Not legal during a snapshot.
380     pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
381         assert!(!self.in_snapshot());
382
383         // If you add a new field to `RegionConstraintCollector`, you
384         // should think carefully about whether it needs to be cleared
385         // or updated in some way.
386         let RegionConstraintCollector {
387             var_infos: _,
388             data,
389             lubs,
390             glbs,
391             undo_log: _,
392             num_open_snapshots: _,
393             unification_table,
394             any_unifications,
395         } = self;
396
397         // Clear the tables of (lubs, glbs), so that we will create
398         // fresh regions if we do a LUB operation. As it happens,
399         // LUB/GLB are not performed by the MIR type-checker, which is
400         // the one that uses this method, but it's good to be correct.
401         lubs.clear();
402         glbs.clear();
403
404         // Clear all unifications and recreate the variables a "now
405         // un-unified" state. Note that when we unify `a` and `b`, we
406         // also insert `a <= b` and a `b <= a` edges, so the
407         // `RegionConstraintData` contains the relationship here.
408         if *any_unifications {
409             unification_table.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
410             *any_unifications = false;
411         }
412
413         mem::replace(data, RegionConstraintData::default())
414     }
415
416     pub fn data(&self) -> &RegionConstraintData<'tcx> {
417         &self.data
418     }
419
420     fn in_snapshot(&self) -> bool {
421         self.num_open_snapshots > 0
422     }
423
424     pub fn start_snapshot(&mut self) -> RegionSnapshot {
425         let length = self.undo_log.len();
426         debug!("RegionConstraintCollector: start_snapshot({})", length);
427         self.num_open_snapshots += 1;
428         RegionSnapshot {
429             length,
430             region_snapshot: self.unification_table.snapshot(),
431             any_unifications: self.any_unifications,
432         }
433     }
434
435     fn assert_open_snapshot(&self, snapshot: &RegionSnapshot) {
436         assert!(self.undo_log.len() >= snapshot.length);
437         assert!(self.num_open_snapshots > 0);
438     }
439
440     pub fn commit(&mut self, snapshot: RegionSnapshot) {
441         debug!("RegionConstraintCollector: commit({})", snapshot.length);
442         self.assert_open_snapshot(&snapshot);
443
444         if self.num_open_snapshots == 1 {
445             // The root snapshot. It's safe to clear the undo log because
446             // there's no snapshot further out that we might need to roll back
447             // to.
448             assert!(snapshot.length == 0);
449             self.undo_log.clear();
450         }
451
452         self.num_open_snapshots -= 1;
453
454         self.unification_table.commit(snapshot.region_snapshot);
455     }
456
457     pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
458         debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
459         self.assert_open_snapshot(&snapshot);
460
461         while self.undo_log.len() > snapshot.length {
462             let undo_entry = self.undo_log.pop().unwrap();
463             self.rollback_undo_entry(undo_entry);
464         }
465
466         self.num_open_snapshots -= 1;
467
468         self.unification_table.rollback_to(snapshot.region_snapshot);
469         self.any_unifications = snapshot.any_unifications;
470     }
471
472     fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
473         match undo_entry {
474             Purged => {
475                 // nothing to do here
476             }
477             AddVar(vid) => {
478                 self.var_infos.pop().unwrap();
479                 assert_eq!(self.var_infos.len(), vid.index() as usize);
480             }
481             AddConstraint(ref constraint) => {
482                 self.data.constraints.remove(constraint);
483             }
484             AddVerify(index) => {
485                 self.data.verifys.pop();
486                 assert_eq!(self.data.verifys.len(), index);
487             }
488             AddGiven(sub, sup) => {
489                 self.data.givens.remove(&(sub, sup));
490             }
491             AddCombination(Glb, ref regions) => {
492                 self.glbs.remove(regions);
493             }
494             AddCombination(Lub, ref regions) => {
495                 self.lubs.remove(regions);
496             }
497         }
498     }
499
500     pub fn new_region_var(
501         &mut self,
502         universe: ty::UniverseIndex,
503         origin: RegionVariableOrigin,
504     ) -> RegionVid {
505         let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
506
507         let u_vid = self
508             .unification_table
509             .new_key(unify_key::RegionVidKey { min_vid: vid });
510         assert_eq!(vid, u_vid);
511         if self.in_snapshot() {
512             self.undo_log.push(AddVar(vid));
513         }
514         debug!(
515             "created new region variable {:?} in {:?} with origin {:?}",
516             vid, universe, origin
517         );
518         return vid;
519     }
520
521     /// Returns the universe for the given variable.
522     pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
523         self.var_infos[vid].universe
524     }
525
526     /// Returns the origin for the given variable.
527     pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
528         self.var_infos[vid].origin
529     }
530
531     /// Removes all the edges to/from the placeholder regions that are
532     /// in `skols`. This is used after a higher-ranked operation
533     /// completes to remove all trace of the placeholder regions
534     /// created in that time.
535     pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
536         debug!("pop_placeholders(placeholders={:?})", placeholders);
537
538         assert!(self.in_snapshot());
539
540         let constraints_to_kill: Vec<usize> = self
541             .undo_log
542             .iter()
543             .enumerate()
544             .rev()
545             .filter(|&(_, undo_entry)| kill_constraint(placeholders, undo_entry))
546             .map(|(index, _)| index)
547             .collect();
548
549         for index in constraints_to_kill {
550             let undo_entry = mem::replace(&mut self.undo_log[index], Purged);
551             self.rollback_undo_entry(undo_entry);
552         }
553
554         return;
555
556         fn kill_constraint<'tcx>(
557             placeholders: &FxHashSet<ty::Region<'tcx>>,
558             undo_entry: &UndoLog<'tcx>,
559         ) -> bool {
560             match undo_entry {
561                 &AddConstraint(Constraint::VarSubVar(..)) => false,
562                 &AddConstraint(Constraint::RegSubVar(a, _)) => placeholders.contains(&a),
563                 &AddConstraint(Constraint::VarSubReg(_, b)) => placeholders.contains(&b),
564                 &AddConstraint(Constraint::RegSubReg(a, b)) => {
565                     placeholders.contains(&a) || placeholders.contains(&b)
566                 }
567                 &AddGiven(..) => false,
568                 &AddVerify(_) => false,
569                 &AddCombination(_, ref two_regions) => {
570                     placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b)
571                 }
572                 &AddVar(..) | &Purged => false,
573             }
574         }
575     }
576
577     fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
578         // cannot add constraints once regions are resolved
579         debug!(
580             "RegionConstraintCollector: add_constraint({:?})",
581             constraint
582         );
583
584         // never overwrite an existing (constraint, origin) - only insert one if it isn't
585         // present in the map yet. This prevents origins from outside the snapshot being
586         // replaced with "less informative" origins e.g., during calls to `can_eq`
587         let in_snapshot = self.in_snapshot();
588         let undo_log = &mut self.undo_log;
589         self.data.constraints.entry(constraint).or_insert_with(|| {
590             if in_snapshot {
591                 undo_log.push(AddConstraint(constraint));
592             }
593             origin
594         });
595     }
596
597     fn add_verify(&mut self, verify: Verify<'tcx>) {
598         // cannot add verifys once regions are resolved
599         debug!("RegionConstraintCollector: add_verify({:?})", verify);
600
601         // skip no-op cases known to be satisfied
602         if let VerifyBound::AllBounds(ref bs) = verify.bound {
603             if bs.len() == 0 {
604                 return;
605             }
606         }
607
608         let index = self.data.verifys.len();
609         self.data.verifys.push(verify);
610         if self.in_snapshot() {
611             self.undo_log.push(AddVerify(index));
612         }
613     }
614
615     pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
616         // cannot add givens once regions are resolved
617         if self.data.givens.insert((sub, sup)) {
618             debug!("add_given({:?} <= {:?})", sub, sup);
619
620             if self.in_snapshot() {
621                 self.undo_log.push(AddGiven(sub, sup));
622             }
623         }
624     }
625
626     pub fn make_eqregion(
627         &mut self,
628         origin: SubregionOrigin<'tcx>,
629         sub: Region<'tcx>,
630         sup: Region<'tcx>,
631     ) {
632         if sub != sup {
633             // Eventually, it would be nice to add direct support for
634             // equating regions.
635             self.make_subregion(origin.clone(), sub, sup);
636             self.make_subregion(origin, sup, sub);
637
638             if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
639                 debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
640                 self.unification_table.union(sub, sup);
641                 self.any_unifications = true;
642             }
643         }
644     }
645
646     pub fn make_subregion(
647         &mut self,
648         origin: SubregionOrigin<'tcx>,
649         sub: Region<'tcx>,
650         sup: Region<'tcx>,
651     ) {
652         // cannot add constraints once regions are resolved
653         debug!(
654             "RegionConstraintCollector: make_subregion({:?}, {:?}) due to {:?}",
655             sub, sup, origin
656         );
657
658         match (sub, sup) {
659             (&ReLateBound(..), _) | (_, &ReLateBound(..)) => {
660                 span_bug!(
661                     origin.span(),
662                     "cannot relate bound region: {:?} <= {:?}",
663                     sub,
664                     sup
665                 );
666             }
667             (_, &ReStatic) => {
668                 // all regions are subregions of static, so we can ignore this
669             }
670             (&ReVar(sub_id), &ReVar(sup_id)) => {
671                 self.add_constraint(Constraint::VarSubVar(sub_id, sup_id), origin);
672             }
673             (_, &ReVar(sup_id)) => {
674                 self.add_constraint(Constraint::RegSubVar(sub, sup_id), origin);
675             }
676             (&ReVar(sub_id), _) => {
677                 self.add_constraint(Constraint::VarSubReg(sub_id, sup), origin);
678             }
679             _ => {
680                 self.add_constraint(Constraint::RegSubReg(sub, sup), origin);
681             }
682         }
683     }
684
685     /// See [`Verify::VerifyGenericBound`].
686     pub fn verify_generic_bound(
687         &mut self,
688         origin: SubregionOrigin<'tcx>,
689         kind: GenericKind<'tcx>,
690         sub: Region<'tcx>,
691         bound: VerifyBound<'tcx>,
692     ) {
693         self.add_verify(Verify {
694             kind,
695             origin,
696             region: sub,
697             bound,
698         });
699     }
700
701     pub fn lub_regions(
702         &mut self,
703         tcx: TyCtxt<'tcx>,
704         origin: SubregionOrigin<'tcx>,
705         a: Region<'tcx>,
706         b: Region<'tcx>,
707     ) -> Region<'tcx> {
708         // cannot add constraints once regions are resolved
709         debug!("RegionConstraintCollector: lub_regions({:?}, {:?})", a, b);
710         match (a, b) {
711             (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
712                 r // nothing lives longer than static
713             }
714
715             _ if a == b => {
716                 a // LUB(a,a) = a
717             }
718
719             _ => self.combine_vars(tcx, Lub, a, b, origin),
720         }
721     }
722
723     pub fn glb_regions(
724         &mut self,
725         tcx: TyCtxt<'tcx>,
726         origin: SubregionOrigin<'tcx>,
727         a: Region<'tcx>,
728         b: Region<'tcx>,
729     ) -> Region<'tcx> {
730         // cannot add constraints once regions are resolved
731         debug!("RegionConstraintCollector: glb_regions({:?}, {:?})", a, b);
732         match (a, b) {
733             (&ReStatic, r) | (r, &ReStatic) => {
734                 r // static lives longer than everything else
735             }
736
737             _ if a == b => {
738                 a // GLB(a,a) = a
739             }
740
741             _ => self.combine_vars(tcx, Glb, a, b, origin),
742         }
743     }
744
745     pub fn opportunistic_resolve_var(
746         &mut self,
747         tcx: TyCtxt<'tcx>,
748         rid: RegionVid,
749     ) -> ty::Region<'tcx> {
750         let vid = self.unification_table.probe_value(rid).min_vid;
751         tcx.mk_region(ty::ReVar(vid))
752     }
753
754     fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
755         match t {
756             Glb => &mut self.glbs,
757             Lub => &mut self.lubs,
758         }
759     }
760
761     fn combine_vars(
762         &mut self,
763         tcx: TyCtxt<'tcx>,
764         t: CombineMapType,
765         a: Region<'tcx>,
766         b: Region<'tcx>,
767         origin: SubregionOrigin<'tcx>,
768     ) -> Region<'tcx> {
769         let vars = TwoRegions { a: a, b: b };
770         if let Some(&c) = self.combine_map(t).get(&vars) {
771             return tcx.mk_region(ReVar(c));
772         }
773         let a_universe = self.universe(a);
774         let b_universe = self.universe(b);
775         let c_universe = cmp::max(a_universe, b_universe);
776         let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
777         self.combine_map(t).insert(vars, c);
778         if self.in_snapshot() {
779             self.undo_log.push(AddCombination(t, vars));
780         }
781         let new_r = tcx.mk_region(ReVar(c));
782         for &old_r in &[a, b] {
783             match t {
784                 Glb => self.make_subregion(origin.clone(), new_r, old_r),
785                 Lub => self.make_subregion(origin.clone(), old_r, new_r),
786             }
787         }
788         debug!("combine_vars() c={:?}", c);
789         new_r
790     }
791
792     pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
793         match *region {
794             ty::ReScope(..)
795             | ty::ReStatic
796             | ty::ReEmpty
797             | ty::ReErased
798             | ty::ReFree(..)
799             | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
800             ty::RePlaceholder(placeholder) => placeholder.universe,
801             ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
802             ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
803         }
804     }
805
806     pub fn vars_since_snapshot(
807         &self,
808         mark: &RegionSnapshot,
809     ) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
810         let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot);
811         (range.clone(), (range.start.index()..range.end.index()).map(|index| {
812             self.var_infos[ty::RegionVid::from(index)].origin.clone()
813         }).collect())
814     }
815
816     /// See [`RegionInference::region_constraints_added_in_snapshot`].
817     pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> Option<bool> {
818         self.undo_log[mark.length..]
819             .iter()
820             .map(|&elt| match elt {
821                 AddConstraint(constraint) => Some(constraint.involves_placeholders()),
822                 _ => None,
823             }).max()
824             .unwrap_or(None)
825     }
826 }
827
828 impl fmt::Debug for RegionSnapshot {
829     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830         write!(f, "RegionSnapshot(length={})", self.length)
831     }
832 }
833
834 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
835     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
836         match *self {
837             GenericKind::Param(ref p) => write!(f, "{:?}", p),
838             GenericKind::Projection(ref p) => write!(f, "{:?}", p),
839         }
840     }
841 }
842
843 impl<'tcx> fmt::Display for GenericKind<'tcx> {
844     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
845         match *self {
846             GenericKind::Param(ref p) => write!(f, "{}", p),
847             GenericKind::Projection(ref p) => write!(f, "{}", p),
848         }
849     }
850 }
851
852 impl<'tcx> GenericKind<'tcx> {
853     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
854         match *self {
855             GenericKind::Param(ref p) => p.to_ty(tcx),
856             GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
857         }
858     }
859 }
860
861 impl<'tcx> VerifyBound<'tcx> {
862     pub fn must_hold(&self) -> bool {
863         match self {
864             VerifyBound::IfEq(..) => false,
865             VerifyBound::OutlivedBy(ty::ReStatic) => true,
866             VerifyBound::OutlivedBy(_) => false,
867             VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.must_hold()),
868             VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.must_hold()),
869         }
870     }
871
872     pub fn cannot_hold(&self) -> bool {
873         match self {
874             VerifyBound::IfEq(_, b) => b.cannot_hold(),
875             VerifyBound::OutlivedBy(ty::ReEmpty) => true,
876             VerifyBound::OutlivedBy(_) => false,
877             VerifyBound::AnyBound(bs) => bs.iter().all(|b| b.cannot_hold()),
878             VerifyBound::AllBounds(bs) => bs.iter().any(|b| b.cannot_hold()),
879         }
880     }
881
882     pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
883         if self.must_hold() || vb.cannot_hold() {
884             self
885         } else if self.cannot_hold() || vb.must_hold() {
886             vb
887         } else {
888             VerifyBound::AnyBound(vec![self, vb])
889         }
890     }
891
892     pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
893         if self.must_hold() && vb.must_hold() {
894             self
895         } else if self.cannot_hold() && vb.cannot_hold() {
896             self
897         } else {
898             VerifyBound::AllBounds(vec![self, vb])
899         }
900     }
901 }
902
903 impl<'tcx> RegionConstraintData<'tcx> {
904     /// Returns `true` if this region constraint data contains no constraints, and `false`
905     /// otherwise.
906     pub fn is_empty(&self) -> bool {
907         let RegionConstraintData {
908             constraints,
909             verifys,
910             givens,
911         } = self;
912         constraints.is_empty() && verifys.is_empty() && givens.is_empty()
913     }
914 }