1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 pub use self::Constraint::*;
14 pub use self::UndoLogEntry::*;
15 pub use self::CombineMapType::*;
16 pub use self::RegionResolutionError::*;
17 pub use self::VarValue::*;
19 use super::{RegionVariableOrigin, SubregionOrigin, MiscVariable};
22 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
23 use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
24 use rustc_data_structures::unify::{self, UnificationTable};
25 use middle::free_region::RegionRelations;
26 use ty::{self, Ty, TyCtxt};
27 use ty::{Region, RegionVid};
28 use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
29 use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
31 use std::cell::{Cell, RefCell};
32 use std::cmp::Ordering::{self, Less, Greater, Equal};
39 // A constraint that influences the inference process.
40 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
41 pub enum Constraint<'tcx> {
42 // One region variable is subregion of another
43 ConstrainVarSubVar(RegionVid, RegionVid),
45 // Concrete region is subregion of region variable
46 ConstrainRegSubVar(Region<'tcx>, RegionVid),
48 // Region variable is subregion of concrete region. This does not
49 // directly affect inference, but instead is checked after
50 // inference is complete.
51 ConstrainVarSubReg(RegionVid, Region<'tcx>),
53 // A constraint where neither side is a variable. This does not
54 // directly affect inference, but instead is checked after
55 // inference is complete.
56 ConstrainRegSubReg(Region<'tcx>, Region<'tcx>),
59 // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
60 // associated type) must outlive the region `R`. `T` is known to
61 // outlive `RS`. Therefore verify that `R <= RS[i]` for some
62 // `i`. Inference variables may be involved (but this verification
63 // step doesn't influence inference).
65 pub struct Verify<'tcx> {
66 kind: GenericKind<'tcx>,
67 origin: SubregionOrigin<'tcx>,
69 bound: VerifyBound<'tcx>,
72 #[derive(Copy, Clone, PartialEq, Eq)]
73 pub enum GenericKind<'tcx> {
75 Projection(ty::ProjectionTy<'tcx>),
78 // When we introduce a verification step, we wish to test that a
79 // particular region (let's call it `'min`) meets some bound.
80 // The bound is described the by the following grammar:
82 pub enum VerifyBound<'tcx> {
83 // B = exists {R} --> some 'r in {R} must outlive 'min
85 // Put another way, the subject value is known to outlive all
86 // regions in {R}, so if any of those outlives 'min, then the
88 AnyRegion(Vec<Region<'tcx>>),
90 // B = forall {R} --> all 'r in {R} must outlive 'min
92 // Put another way, the subject value is known to outlive some
93 // region in {R}, so if all of those outlives 'min, then the bound
95 AllRegions(Vec<Region<'tcx>>),
97 // B = exists {B} --> 'min must meet some bound b in {B}
98 AnyBound(Vec<VerifyBound<'tcx>>),
100 // B = forall {B} --> 'min must meet all bounds b in {B}
101 AllBounds(Vec<VerifyBound<'tcx>>),
104 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
105 pub struct TwoRegions<'tcx> {
110 #[derive(Copy, Clone, PartialEq)]
111 pub enum UndoLogEntry<'tcx> {
112 /// Pushed when we start a snapshot.
115 /// Replaces an `OpenSnapshot` when a snapshot is committed, but
116 /// that snapshot is not the root. If the root snapshot is
117 /// unrolled, all nested snapshots must be committed.
120 /// We added `RegionVid`
123 /// We added the given `constraint`
124 AddConstraint(Constraint<'tcx>),
126 /// We added the given `verify`
129 /// We added the given `given`
130 AddGiven(ty::FreeRegion<'tcx>, ty::RegionVid),
132 /// We added a GLB/LUB "combinaton variable"
133 AddCombination(CombineMapType, TwoRegions<'tcx>),
135 /// During skolemization, we sometimes purge entries from the undo
136 /// log in a kind of minisnapshot (unlike other snapshots, this
137 /// purging actually takes place *on success*). In that case, we
138 /// replace the corresponding entry with `Noop` so as to avoid the
139 /// need to do a bunch of swapping. (We can't use `swap_remove` as
140 /// the order of the vector is important.)
144 #[derive(Copy, Clone, PartialEq)]
145 pub enum CombineMapType {
150 #[derive(Clone, Debug)]
151 pub enum RegionResolutionError<'tcx> {
152 /// `ConcreteFailure(o, a, b)`:
154 /// `o` requires that `a <= b`, but this does not hold
155 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
157 /// `GenericBoundFailure(p, s, a)
159 /// The parameter/associated-type `p` must be known to outlive the lifetime
160 /// `a` (but none of the known bounds are sufficient).
161 GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>),
163 /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
165 /// Could not infer a value for `v` because `sub_r <= v` (due to
166 /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
167 /// `sub_r <= sup_r` does not hold.
168 SubSupConflict(RegionVariableOrigin,
169 SubregionOrigin<'tcx>,
171 SubregionOrigin<'tcx>,
175 #[derive(Clone, Debug)]
176 pub enum ProcessedErrorOrigin<'tcx> {
177 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
178 VariableFailure(RegionVariableOrigin),
181 pub type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
183 pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
184 tcx: TyCtxt<'a, 'gcx, 'tcx>,
185 var_origins: RefCell<Vec<RegionVariableOrigin>>,
187 // Constraints of the form `A <= B` introduced by the region
188 // checker. Here at least one of `A` and `B` must be a region
190 constraints: RefCell<FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
192 // A "verify" is something that we need to verify after inference is
193 // done, but which does not directly affect inference in any way.
195 // An example is a `A <= B` where neither `A` nor `B` are
196 // inference variables.
197 verifys: RefCell<Vec<Verify<'tcx>>>,
199 // A "given" is a relationship that is known to hold. In particular,
200 // we often know from closure fn signatures that a particular free
201 // region must be a subregion of a region variable:
203 // foo.iter().filter(<'a> |x: &'a &'b T| ...)
205 // In situations like this, `'b` is in fact a region variable
206 // introduced by the call to `iter()`, and `'a` is a bound region
207 // on the closure (as indicated by the `<'a>` prefix). If we are
208 // naive, we wind up inferring that `'b` must be `'static`,
209 // because we require that it be greater than `'a` and we do not
210 // know what `'a` is precisely.
212 // This hashmap is used to avoid that naive scenario. Basically we
213 // record the fact that `'a <= 'b` is implied by the fn signature,
214 // and then ignore the constraint when solving equations. This is
215 // a bit of a hack but seems to work.
216 givens: RefCell<FxHashSet<(ty::FreeRegion<'tcx>, ty::RegionVid)>>,
218 lubs: RefCell<CombineMap<'tcx>>,
219 glbs: RefCell<CombineMap<'tcx>>,
220 skolemization_count: Cell<u32>,
221 bound_count: Cell<u32>,
223 // The undo log records actions that might later be undone.
225 // Note: when the undo_log is empty, we are not actively
226 // snapshotting. When the `start_snapshot()` method is called, we
227 // push an OpenSnapshot entry onto the list to indicate that we
228 // are now actively snapshotting. The reason for this is that
229 // otherwise we end up adding entries for things like the lower
230 // bound on a variable and so forth, which can never be rolled
232 undo_log: RefCell<Vec<UndoLogEntry<'tcx>>>,
233 unification_table: RefCell<UnificationTable<ty::RegionVid>>,
235 // This contains the results of inference. It begins as an empty
236 // option and only acquires a value after inference is complete.
237 values: RefCell<Option<Vec<VarValue<'tcx>>>>,
240 pub struct RegionSnapshot {
242 region_snapshot: unify::Snapshot<ty::RegionVid>,
243 skolemization_count: u32,
246 /// When working with skolemized regions, we often wish to find all of
247 /// the regions that are either reachable from a skolemized region, or
248 /// which can reach a skolemized region, or both. We call such regions
249 /// *tained* regions. This struct allows you to decide what set of
250 /// tainted regions you want.
252 pub struct TaintDirections {
257 impl TaintDirections {
258 pub fn incoming() -> Self {
259 TaintDirections { incoming: true, outgoing: false }
262 pub fn outgoing() -> Self {
263 TaintDirections { incoming: false, outgoing: true }
266 pub fn both() -> Self {
267 TaintDirections { incoming: true, outgoing: true }
271 struct TaintSet<'tcx> {
272 directions: TaintDirections,
273 regions: FxHashSet<ty::Region<'tcx>>
276 impl<'a, 'gcx, 'tcx> TaintSet<'tcx> {
277 fn new(directions: TaintDirections,
278 initial_region: ty::Region<'tcx>)
280 let mut regions = FxHashSet();
281 regions.insert(initial_region);
282 TaintSet { directions: directions, regions: regions }
285 fn fixed_point(&mut self,
286 tcx: TyCtxt<'a, 'gcx, 'tcx>,
287 undo_log: &[UndoLogEntry<'tcx>],
288 verifys: &[Verify<'tcx>]) {
289 let mut prev_len = 0;
290 while prev_len < self.len() {
291 debug!("tainted: prev_len = {:?} new_len = {:?}",
292 prev_len, self.len());
294 prev_len = self.len();
296 for undo_entry in undo_log {
298 &AddConstraint(ConstrainVarSubVar(a, b)) => {
299 self.add_edge(tcx.mk_region(ReVar(a)),
300 tcx.mk_region(ReVar(b)));
302 &AddConstraint(ConstrainRegSubVar(a, b)) => {
303 self.add_edge(a, tcx.mk_region(ReVar(b)));
305 &AddConstraint(ConstrainVarSubReg(a, b)) => {
306 self.add_edge(tcx.mk_region(ReVar(a)), b);
308 &AddConstraint(ConstrainRegSubReg(a, b)) => {
312 self.add_edge(tcx.mk_region(ReFree(a)),
313 tcx.mk_region(ReVar(b)));
316 verifys[i].bound.for_each_region(&mut |b| {
317 self.add_edge(verifys[i].region, b);
321 &AddCombination(..) |
324 &CommitedSnapshot => {}
330 fn into_set(self) -> FxHashSet<ty::Region<'tcx>> {
334 fn len(&self) -> usize {
338 fn add_edge(&mut self,
339 source: ty::Region<'tcx>,
340 target: ty::Region<'tcx>) {
341 if self.directions.incoming {
342 if self.regions.contains(&target) {
343 self.regions.insert(source);
347 if self.directions.outgoing {
348 if self.regions.contains(&source) {
349 self.regions.insert(target);
355 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
356 pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
359 var_origins: RefCell::new(Vec::new()),
360 values: RefCell::new(None),
361 constraints: RefCell::new(FxHashMap()),
362 verifys: RefCell::new(Vec::new()),
363 givens: RefCell::new(FxHashSet()),
364 lubs: RefCell::new(FxHashMap()),
365 glbs: RefCell::new(FxHashMap()),
366 skolemization_count: Cell::new(0),
367 bound_count: Cell::new(0),
368 undo_log: RefCell::new(Vec::new()),
369 unification_table: RefCell::new(UnificationTable::new()),
373 fn in_snapshot(&self) -> bool {
374 !self.undo_log.borrow().is_empty()
377 pub fn start_snapshot(&self) -> RegionSnapshot {
378 let length = self.undo_log.borrow().len();
379 debug!("RegionVarBindings: start_snapshot({})", length);
380 self.undo_log.borrow_mut().push(OpenSnapshot);
383 region_snapshot: self.unification_table.borrow_mut().snapshot(),
384 skolemization_count: self.skolemization_count.get(),
388 pub fn commit(&self, snapshot: RegionSnapshot) {
389 debug!("RegionVarBindings: commit({})", snapshot.length);
390 assert!(self.undo_log.borrow().len() > snapshot.length);
391 assert!((*self.undo_log.borrow())[snapshot.length] == OpenSnapshot);
392 assert!(self.skolemization_count.get() == snapshot.skolemization_count,
393 "failed to pop skolemized regions: {} now vs {} at start",
394 self.skolemization_count.get(),
395 snapshot.skolemization_count);
397 let mut undo_log = self.undo_log.borrow_mut();
398 if snapshot.length == 0 {
399 undo_log.truncate(0);
401 (*undo_log)[snapshot.length] = CommitedSnapshot;
403 self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
406 pub fn rollback_to(&self, snapshot: RegionSnapshot) {
407 debug!("RegionVarBindings: rollback_to({:?})", snapshot);
408 let mut undo_log = self.undo_log.borrow_mut();
409 assert!(undo_log.len() > snapshot.length);
410 assert!((*undo_log)[snapshot.length] == OpenSnapshot);
411 while undo_log.len() > snapshot.length + 1 {
412 self.rollback_undo_entry(undo_log.pop().unwrap());
414 let c = undo_log.pop().unwrap();
415 assert!(c == OpenSnapshot);
416 self.skolemization_count.set(snapshot.skolemization_count);
417 self.unification_table.borrow_mut()
418 .rollback_to(snapshot.region_snapshot);
421 pub fn rollback_undo_entry(&self, undo_entry: UndoLogEntry<'tcx>) {
424 panic!("Failure to observe stack discipline");
426 Purged | CommitedSnapshot => {
427 // nothing to do here
430 let mut var_origins = self.var_origins.borrow_mut();
431 var_origins.pop().unwrap();
432 assert_eq!(var_origins.len(), vid.index as usize);
434 AddConstraint(ref constraint) => {
435 self.constraints.borrow_mut().remove(constraint);
437 AddVerify(index) => {
438 self.verifys.borrow_mut().pop();
439 assert_eq!(self.verifys.borrow().len(), index);
441 AddGiven(sub, sup) => {
442 self.givens.borrow_mut().remove(&(sub, sup));
444 AddCombination(Glb, ref regions) => {
445 self.glbs.borrow_mut().remove(regions);
447 AddCombination(Lub, ref regions) => {
448 self.lubs.borrow_mut().remove(regions);
453 pub fn num_vars(&self) -> u32 {
454 let len = self.var_origins.borrow().len();
455 // enforce no overflow
456 assert!(len as u32 as usize == len);
460 pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
461 let vid = RegionVid { index: self.num_vars() };
462 self.var_origins.borrow_mut().push(origin.clone());
464 let u_vid = self.unification_table.borrow_mut().new_key(
465 unify_key::RegionVidKey { min_vid: vid }
467 assert_eq!(vid, u_vid);
468 if self.in_snapshot() {
469 self.undo_log.borrow_mut().push(AddVar(vid));
471 debug!("created new region variable {:?} with origin {:?}",
477 pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
478 self.var_origins.borrow()[vid.index as usize].clone()
481 /// Creates a new skolemized region. Skolemized regions are fresh
482 /// regions used when performing higher-ranked computations. They
483 /// must be used in a very particular way and are never supposed
484 /// to "escape" out into error messages or the code at large.
486 /// The idea is to always create a snapshot. Skolemized regions
487 /// can be created in the context of this snapshot, but before the
488 /// snapshot is committed or rolled back, they must be popped
489 /// (using `pop_skolemized_regions`), so that their numbers can be
490 /// recycled. Normally you don't have to think about this: you use
491 /// the APIs in `higher_ranked/mod.rs`, such as
492 /// `skolemize_late_bound_regions` and `plug_leaks`, which will
493 /// guide you on this path (ensure that the `SkolemizationMap` is
494 /// consumed and you are good). There are also somewhat extensive
495 /// comments in `higher_ranked/README.md`.
497 /// The `snapshot` argument to this function is not really used;
498 /// it's just there to make it explicit which snapshot bounds the
499 /// skolemized region that results. It should always be the top-most snapshot.
500 pub fn push_skolemized(&self, br: ty::BoundRegion, snapshot: &RegionSnapshot)
502 assert!(self.in_snapshot());
503 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
505 let sc = self.skolemization_count.get();
506 self.skolemization_count.set(sc + 1);
507 self.tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
510 /// Removes all the edges to/from the skolemized regions that are
511 /// in `skols`. This is used after a higher-ranked operation
512 /// completes to remove all trace of the skolemized regions
513 /// created in that time.
514 pub fn pop_skolemized(&self,
515 skols: &FxHashSet<ty::Region<'tcx>>,
516 snapshot: &RegionSnapshot) {
517 debug!("pop_skolemized_regions(skols={:?})", skols);
519 assert!(self.in_snapshot());
520 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
521 assert!(self.skolemization_count.get() as usize >= skols.len(),
522 "popping more skolemized variables than actually exist, \
523 sc now = {}, skols.len = {}",
524 self.skolemization_count.get(),
527 let last_to_pop = self.skolemization_count.get();
528 let first_to_pop = last_to_pop - (skols.len() as u32);
530 assert!(first_to_pop >= snapshot.skolemization_count,
531 "popping more regions than snapshot contains, \
532 sc now = {}, sc then = {}, skols.len = {}",
533 self.skolemization_count.get(),
534 snapshot.skolemization_count,
539 ty::ReSkolemized(index, _) =>
540 index.index >= first_to_pop &&
541 index.index < last_to_pop,
545 "invalid skolemization keys or keys out of range ({}..{}): {:?}",
546 snapshot.skolemization_count,
547 self.skolemization_count.get(),
551 let mut undo_log = self.undo_log.borrow_mut();
553 let constraints_to_kill: Vec<usize> =
557 .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry))
558 .map(|(index, _)| index)
561 for index in constraints_to_kill {
562 let undo_entry = mem::replace(&mut undo_log[index], Purged);
563 self.rollback_undo_entry(undo_entry);
566 self.skolemization_count.set(snapshot.skolemization_count);
569 fn kill_constraint<'tcx>(skols: &FxHashSet<ty::Region<'tcx>>,
570 undo_entry: &UndoLogEntry<'tcx>)
573 &AddConstraint(ConstrainVarSubVar(..)) =>
575 &AddConstraint(ConstrainRegSubVar(a, _)) =>
577 &AddConstraint(ConstrainVarSubReg(_, b)) =>
579 &AddConstraint(ConstrainRegSubReg(a, b)) =>
580 skols.contains(&a) || skols.contains(&b),
585 &AddCombination(_, ref two_regions) =>
586 skols.contains(&two_regions.a) ||
587 skols.contains(&two_regions.b),
598 pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> Region<'tcx> {
599 // Creates a fresh bound variable for use in GLB computations.
600 // See discussion of GLB computation in the large comment at
601 // the top of this file for more details.
603 // This computation is potentially wrong in the face of
604 // rollover. It's conceivable, if unlikely, that one might
605 // wind up with accidental capture for nested functions in
606 // that case, if the outer function had bound regions created
607 // a very long time before and the inner function somehow
608 // wound up rolling over such that supposedly fresh
609 // identifiers were in fact shadowed. For now, we just assert
610 // that there is no rollover -- eventually we should try to be
611 // robust against this possibility, either by checking the set
612 // of bound identifiers that appear in a given expression and
613 // ensure that we generate one that is distinct, or by
614 // changing the representation of bound regions in a fn
617 let sc = self.bound_count.get();
618 self.bound_count.set(sc + 1);
620 if sc >= self.bound_count.get() {
621 bug!("rollover in RegionInference new_bound()");
624 self.tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
627 fn values_are_none(&self) -> bool {
628 self.values.borrow().is_none()
631 fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
632 // cannot add constraints once regions are resolved
633 assert!(self.values_are_none());
635 debug!("RegionVarBindings: add_constraint({:?})", constraint);
637 if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
638 if self.in_snapshot() {
639 self.undo_log.borrow_mut().push(AddConstraint(constraint));
644 fn add_verify(&self, verify: Verify<'tcx>) {
645 // cannot add verifys once regions are resolved
646 assert!(self.values_are_none());
648 debug!("RegionVarBindings: add_verify({:?})", verify);
650 // skip no-op cases known to be satisfied
652 VerifyBound::AllBounds(ref bs) if bs.len() == 0 => { return; }
656 let mut verifys = self.verifys.borrow_mut();
657 let index = verifys.len();
658 verifys.push(verify);
659 if self.in_snapshot() {
660 self.undo_log.borrow_mut().push(AddVerify(index));
664 pub fn add_given(&self, sub: ty::FreeRegion<'tcx>, sup: ty::RegionVid) {
665 // cannot add givens once regions are resolved
666 assert!(self.values_are_none());
668 let mut givens = self.givens.borrow_mut();
669 if givens.insert((sub, sup)) {
670 debug!("add_given({:?} <= {:?})", sub, sup);
672 self.undo_log.borrow_mut().push(AddGiven(sub, sup));
676 pub fn make_eqregion(&self,
677 origin: SubregionOrigin<'tcx>,
681 // Eventually, it would be nice to add direct support for
683 self.make_subregion(origin.clone(), sub, sup);
684 self.make_subregion(origin, sup, sub);
686 if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
687 self.unification_table.borrow_mut().union(sub, sup);
692 pub fn make_subregion(&self,
693 origin: SubregionOrigin<'tcx>,
696 // cannot add constraints once regions are resolved
697 assert!(self.values_are_none());
699 debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
705 (&ReEarlyBound(..), _) |
706 (&ReLateBound(..), _) |
707 (_, &ReEarlyBound(..)) |
708 (_, &ReLateBound(..)) => {
709 span_bug!(origin.span(),
710 "cannot relate bound region: {:?} <= {:?}",
715 // all regions are subregions of static, so we can ignore this
717 (&ReVar(sub_id), &ReVar(sup_id)) => {
718 self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
720 (_, &ReVar(sup_id)) => {
721 self.add_constraint(ConstrainRegSubVar(sub, sup_id), origin);
723 (&ReVar(sub_id), _) => {
724 self.add_constraint(ConstrainVarSubReg(sub_id, sup), origin);
727 self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
732 /// See `Verify::VerifyGenericBound`
733 pub fn verify_generic_bound(&self,
734 origin: SubregionOrigin<'tcx>,
735 kind: GenericKind<'tcx>,
737 bound: VerifyBound<'tcx>) {
738 self.add_verify(Verify {
746 pub fn lub_regions(&self,
747 origin: SubregionOrigin<'tcx>,
751 // cannot add constraints once regions are resolved
752 assert!(self.values_are_none());
754 debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b);
756 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
757 r // nothing lives longer than static
765 self.combine_vars(Lub, a, b, origin.clone(), |this, old_r, new_r| {
766 this.make_subregion(origin.clone(), old_r, new_r)
772 pub fn glb_regions(&self,
773 origin: SubregionOrigin<'tcx>,
777 // cannot add constraints once regions are resolved
778 assert!(self.values_are_none());
780 debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b);
782 (&ReStatic, r) | (r, &ReStatic) => {
783 r // static lives longer than everything else
791 self.combine_vars(Glb, a, b, origin.clone(), |this, old_r, new_r| {
792 this.make_subregion(origin.clone(), new_r, old_r)
798 pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
799 match *self.values.borrow() {
801 span_bug!((*self.var_origins.borrow())[rid.index as usize].span(),
802 "attempt to resolve region variable before values have \
805 Some(ref values) => {
806 let r = lookup(self.tcx, values, rid);
807 debug!("resolve_var({:?}) = {:?}", rid, r);
813 pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
814 let vid = self.unification_table.borrow_mut().find_value(rid).min_vid;
815 self.tcx.mk_region(ty::ReVar(vid))
818 fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap<'tcx>> {
825 pub fn combine_vars<F>(&self,
829 origin: SubregionOrigin<'tcx>,
832 where F: FnMut(&RegionVarBindings<'a, 'gcx, 'tcx>, Region<'tcx>, Region<'tcx>)
834 let vars = TwoRegions { a: a, b: b };
835 if let Some(&c) = self.combine_map(t).borrow().get(&vars) {
836 return self.tcx.mk_region(ReVar(c));
838 let c = self.new_region_var(MiscVariable(origin.span()));
839 self.combine_map(t).borrow_mut().insert(vars, c);
840 if self.in_snapshot() {
841 self.undo_log.borrow_mut().push(AddCombination(t, vars));
843 relate(self, a, self.tcx.mk_region(ReVar(c)));
844 relate(self, b, self.tcx.mk_region(ReVar(c)));
845 debug!("combine_vars() c={:?}", c);
846 self.tcx.mk_region(ReVar(c))
849 pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
850 self.undo_log.borrow()[mark.length..]
854 AddVar(vid) => Some(vid),
861 /// Computes all regions that have been related to `r0` since the
862 /// mark `mark` was made---`r0` itself will be the first
863 /// entry. The `directions` parameter controls what kind of
864 /// relations are considered. For example, one can say that only
865 /// "incoming" edges to `r0` are desired, in which case one will
866 /// get the set of regions `{r|r <= r0}`. This is used when
867 /// checking whether skolemized regions are being improperly
868 /// related to other regions.
869 pub fn tainted(&self,
870 mark: &RegionSnapshot,
872 directions: TaintDirections)
873 -> FxHashSet<ty::Region<'tcx>> {
874 debug!("tainted(mark={:?}, r0={:?}, directions={:?})",
875 mark, r0, directions);
877 // `result_set` acts as a worklist: we explore all outgoing
878 // edges and add any new regions we find to result_set. This
879 // is not a terribly efficient implementation.
880 let mut taint_set = TaintSet::new(directions, r0);
881 taint_set.fixed_point(self.tcx,
882 &self.undo_log.borrow()[mark.length..],
883 &self.verifys.borrow());
884 debug!("tainted: result={:?}", taint_set.regions);
885 return taint_set.into_set();
888 /// This function performs the actual region resolution. It must be
889 /// called after all constraints have been added. It performs a
890 /// fixed-point iteration to find region values which satisfy all
891 /// constraints, assuming such values can be found; if they cannot,
892 /// errors are reported.
893 pub fn resolve_regions(&self,
894 region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
895 -> Vec<RegionResolutionError<'tcx>> {
896 debug!("RegionVarBindings: resolve_regions()");
897 let mut errors = vec![];
898 let v = self.infer_variable_values(region_rels, &mut errors);
899 *self.values.borrow_mut() = Some(v);
903 fn lub_concrete_regions(&self,
904 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
909 (&ReLateBound(..), _) |
910 (_, &ReLateBound(..)) |
911 (&ReEarlyBound(..), _) |
912 (_, &ReEarlyBound(..)) |
915 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
918 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
919 r // nothing lives longer than static
922 (&ReEmpty, r) | (r, &ReEmpty) => {
923 r // everything lives longer than empty
926 (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
927 span_bug!((*self.var_origins.borrow())[v_id.index as usize].span(),
928 "lub_concrete_regions invoked with non-concrete \
929 regions: {:?}, {:?}",
934 (&ReFree(fr), &ReScope(s_id)) |
935 (&ReScope(s_id), &ReFree(fr)) => {
936 // A "free" region can be interpreted as "some region
937 // at least as big as the block fr.scope_id". So, we can
938 // reasonably compare free regions and scopes:
939 if let Some(fr_scope) = fr.scope {
940 let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
941 if r_id == fr_scope {
942 // if the free region's scope `fr.scope_id` is bigger than
943 // the scope region `s_id`, then the LUB is the free
945 return self.tcx.mk_region(ReFree(fr));
949 // otherwise, we don't know what the free region is,
950 // so we must conservatively say the LUB is static:
951 self.tcx.types.re_static
954 (&ReScope(a_id), &ReScope(b_id)) => {
955 // The region corresponding to an outer block is a
956 // subtype of the region corresponding to an inner
958 let lub = region_rels.region_maps.nearest_common_ancestor(a_id, b_id);
959 self.tcx.mk_region(ReScope(lub))
962 (&ReFree(_), &ReFree(_)) => {
963 region_rels.lub_free_regions(a, b)
966 // For these types, we cannot define any additional
968 (&ReSkolemized(..), _) |
969 (_, &ReSkolemized(..)) => {
973 self.tcx.types.re_static
980 // ______________________________________________________________________
982 #[derive(Copy, Clone, Debug)]
983 pub enum VarValue<'tcx> {
988 struct RegionAndOrigin<'tcx> {
989 region: Region<'tcx>,
990 origin: SubregionOrigin<'tcx>,
993 type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
995 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
996 fn infer_variable_values(&self,
997 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
998 errors: &mut Vec<RegionResolutionError<'tcx>>)
999 -> Vec<VarValue<'tcx>> {
1000 let mut var_data = self.construct_var_data();
1002 // Dorky hack to cause `dump_constraints` to only get called
1003 // if debug mode is enabled:
1004 debug!("----() End constraint listing (context={:?}) {:?}---",
1005 region_rels.context,
1006 self.dump_constraints(region_rels));
1007 graphviz::maybe_print_constraints_for(self, region_rels);
1009 let graph = self.construct_graph();
1010 self.expand_givens(&graph);
1011 self.expansion(region_rels, &mut var_data);
1012 self.collect_errors(region_rels, &mut var_data, errors);
1013 self.collect_var_errors(region_rels, &var_data, &graph, errors);
1017 fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
1018 (0..self.num_vars() as usize)
1019 .map(|_| Value(self.tcx.types.re_empty))
1023 fn dump_constraints(&self, free_regions: &RegionRelations<'a, 'gcx, 'tcx>) {
1024 debug!("----() Start constraint listing (context={:?}) ()----",
1025 free_regions.context);
1026 for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
1027 debug!("Constraint {} => {:?}", idx, constraint);
1031 fn expand_givens(&self, graph: &RegionGraph) {
1032 // Givens are a kind of horrible hack to account for
1033 // constraints like 'c <= '0 that are known to hold due to
1034 // closure signatures (see the comment above on the `givens`
1035 // field). They should go away. But until they do, the role
1036 // of this fn is to account for the transitive nature:
1042 let mut givens = self.givens.borrow_mut();
1043 let seeds: Vec<_> = givens.iter().cloned().collect();
1044 for (fr, vid) in seeds {
1045 let seed_index = NodeIndex(vid.index as usize);
1046 for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
1047 let succ_index = succ_index.0 as u32;
1048 if succ_index < self.num_vars() {
1049 let succ_vid = RegionVid { index: succ_index };
1050 givens.insert((fr, succ_vid));
1057 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1058 var_values: &mut [VarValue<'tcx>]) {
1059 self.iterate_until_fixed_point("Expansion", |constraint, origin| {
1060 debug!("expansion: constraint={:?} origin={:?}",
1061 constraint, origin);
1063 ConstrainRegSubVar(a_region, b_vid) => {
1064 let b_data = &mut var_values[b_vid.index as usize];
1065 self.expand_node(region_rels, a_region, b_vid, b_data)
1067 ConstrainVarSubVar(a_vid, b_vid) => {
1068 match var_values[a_vid.index as usize] {
1069 ErrorValue => false,
1070 Value(a_region) => {
1071 let b_node = &mut var_values[b_vid.index as usize];
1072 self.expand_node(region_rels, a_region, b_vid, b_node)
1076 ConstrainRegSubReg(..) |
1077 ConstrainVarSubReg(..) => {
1078 // These constraints are checked after expansion
1079 // is done, in `collect_errors`.
1086 fn expand_node(&self,
1087 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1088 a_region: Region<'tcx>,
1090 b_data: &mut VarValue<'tcx>)
1092 debug!("expand_node({:?}, {:?} == {:?})",
1097 // Check if this relationship is implied by a given.
1100 if self.givens.borrow().contains(&(fr, b_vid)) {
1109 Value(cur_region) => {
1110 let lub = self.lub_concrete_regions(region_rels, a_region, cur_region);
1111 if lub == cur_region {
1115 debug!("Expanding value of {:?} from {:?} to {:?}",
1120 *b_data = Value(lub);
1130 /// After expansion is complete, go and check upper bounds (i.e.,
1131 /// cases where the region cannot grow larger than a fixed point)
1132 /// and check that they are satisfied.
1133 fn collect_errors(&self,
1134 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1135 var_data: &mut Vec<VarValue<'tcx>>,
1136 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1137 let constraints = self.constraints.borrow();
1138 for (constraint, origin) in constraints.iter() {
1139 debug!("collect_errors: constraint={:?} origin={:?}",
1140 constraint, origin);
1142 ConstrainRegSubVar(..) |
1143 ConstrainVarSubVar(..) => {
1144 // Expansion will ensure that these constraints hold. Ignore.
1147 ConstrainRegSubReg(sub, sup) => {
1148 if region_rels.is_subregion_of(sub, sup) {
1152 debug!("collect_errors: region error at {:?}: \
1153 cannot verify that {:?} <= {:?}",
1158 errors.push(ConcreteFailure((*origin).clone(), sub, sup));
1161 ConstrainVarSubReg(a_vid, b_region) => {
1162 let a_data = &mut var_data[a_vid.index as usize];
1163 debug!("contraction: {:?} == {:?}, {:?}",
1168 let a_region = match *a_data {
1169 ErrorValue => continue,
1170 Value(a_region) => a_region,
1173 // Do not report these errors immediately:
1174 // instead, set the variable value to error and
1175 // collect them later.
1176 if !region_rels.is_subregion_of(a_region, b_region) {
1177 debug!("collect_errors: region error at {:?}: \
1178 cannot verify that {:?}={:?} <= {:?}",
1183 *a_data = ErrorValue;
1189 for verify in self.verifys.borrow().iter() {
1190 debug!("collect_errors: verify={:?}", verify);
1191 let sub = normalize(self.tcx, var_data, verify.region);
1192 if verify.bound.is_met(region_rels, var_data, sub) {
1196 debug!("collect_errors: region error at {:?}: \
1197 cannot verify that {:?} <= {:?}",
1202 errors.push(GenericBoundFailure(verify.origin.clone(),
1203 verify.kind.clone(),
1208 /// Go over the variables that were declared to be error variables
1209 /// and create a `RegionResolutionError` for each of them.
1210 fn collect_var_errors(&self,
1211 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1212 var_data: &[VarValue<'tcx>],
1213 graph: &RegionGraph<'tcx>,
1214 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1215 debug!("collect_var_errors");
1217 // This is the best way that I have found to suppress
1218 // duplicate and related errors. Basically we keep a set of
1219 // flags for every node. Whenever an error occurs, we will
1220 // walk some portion of the graph looking to find pairs of
1221 // conflicting regions to report to the user. As we walk, we
1222 // trip the flags from false to true, and if we find that
1223 // we've already reported an error involving any particular
1224 // node we just stop and don't report the current error. The
1225 // idea is to report errors that derive from independent
1226 // regions of the graph, but not those that derive from
1227 // overlapping locations.
1228 let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
1230 for idx in 0..self.num_vars() as usize {
1231 match var_data[idx] {
1233 /* Inference successful */
1236 /* Inference impossible, this value contains
1237 inconsistent constraints.
1239 I think that in this case we should report an
1240 error now---unlike the case above, we can't
1241 wait to see whether the user needs the result
1242 of this variable. The reason is that the mere
1243 existence of this variable implies that the
1244 region graph is inconsistent, whether or not it
1247 For example, we may have created a region
1248 variable that is the GLB of two other regions
1249 which do not have a GLB. Even if that variable
1250 is not used, it implies that those two regions
1251 *should* have a GLB.
1253 At least I think this is true. It may be that
1254 the mere existence of a conflict in a region variable
1255 that is not used is not a problem, so if this rule
1256 starts to create problems we'll have to revisit
1257 this portion of the code and think hard about it. =) */
1259 let node_vid = RegionVid { index: idx as u32 };
1260 self.collect_error_for_expanding_node(region_rels,
1270 fn construct_graph(&self) -> RegionGraph<'tcx> {
1271 let num_vars = self.num_vars();
1273 let constraints = self.constraints.borrow();
1275 let mut graph = graph::Graph::new();
1277 for _ in 0..num_vars {
1281 // Issue #30438: two distinct dummy nodes, one for incoming
1282 // edges (dummy_source) and another for outgoing edges
1283 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
1284 // dummy node leads one to think (erroneously) there exists a
1285 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
1286 let dummy_source = graph.add_node(());
1287 let dummy_sink = graph.add_node(());
1289 for (constraint, _) in constraints.iter() {
1291 ConstrainVarSubVar(a_id, b_id) => {
1292 graph.add_edge(NodeIndex(a_id.index as usize),
1293 NodeIndex(b_id.index as usize),
1296 ConstrainRegSubVar(_, b_id) => {
1297 graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
1299 ConstrainVarSubReg(a_id, _) => {
1300 graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
1302 ConstrainRegSubReg(..) => {
1303 // this would be an edge from `dummy_source` to
1304 // `dummy_sink`; just ignore it.
1312 fn collect_error_for_expanding_node(&self,
1313 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1314 graph: &RegionGraph<'tcx>,
1315 dup_vec: &mut [u32],
1316 node_idx: RegionVid,
1317 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1318 // Errors in expanding nodes result from a lower-bound that is
1319 // not contained by an upper-bound.
1320 let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph,
1324 let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph,
1329 if lower_dup || upper_dup {
1333 // We place free regions first because we are special casing
1334 // SubSupConflict(ReFree, ReFree) when reporting error, and so
1335 // the user will more likely get a specific suggestion.
1336 fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
1337 match (a.region, b.region) {
1338 (&ReFree(..), &ReFree(..)) => Equal,
1339 (&ReFree(..), _) => Less,
1340 (_, &ReFree(..)) => Greater,
1344 lower_bounds.sort_by(|a, b| free_regions_first(a, b));
1345 upper_bounds.sort_by(|a, b| free_regions_first(a, b));
1347 for lower_bound in &lower_bounds {
1348 for upper_bound in &upper_bounds {
1349 if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
1350 let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1351 debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
1356 upper_bound.region);
1357 errors.push(SubSupConflict(origin,
1358 lower_bound.origin.clone(),
1360 upper_bound.origin.clone(),
1361 upper_bound.region));
1367 span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
1368 "collect_error_for_expanding_node() could not find \
1369 error for var {:?}, lower_bounds={:?}, \
1376 fn collect_concrete_regions(&self,
1377 graph: &RegionGraph<'tcx>,
1378 orig_node_idx: RegionVid,
1380 dup_vec: &mut [u32])
1381 -> (Vec<RegionAndOrigin<'tcx>>, bool) {
1382 struct WalkState<'tcx> {
1383 set: FxHashSet<RegionVid>,
1384 stack: Vec<RegionVid>,
1385 result: Vec<RegionAndOrigin<'tcx>>,
1388 let mut state = WalkState {
1390 stack: vec![orig_node_idx],
1394 state.set.insert(orig_node_idx);
1396 // to start off the process, walk the source node in the
1397 // direction specified
1398 process_edges(self, &mut state, graph, orig_node_idx, dir);
1400 while !state.stack.is_empty() {
1401 let node_idx = state.stack.pop().unwrap();
1403 // check whether we've visited this node on some previous walk
1404 if dup_vec[node_idx.index as usize] == u32::MAX {
1405 dup_vec[node_idx.index as usize] = orig_node_idx.index;
1406 } else if dup_vec[node_idx.index as usize] != orig_node_idx.index {
1407 state.dup_found = true;
1410 debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
1414 process_edges(self, &mut state, graph, node_idx, dir);
1417 let WalkState {result, dup_found, ..} = state;
1418 return (result, dup_found);
1420 fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
1421 state: &mut WalkState<'tcx>,
1422 graph: &RegionGraph<'tcx>,
1423 source_vid: RegionVid,
1425 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
1427 let source_node_index = NodeIndex(source_vid.index as usize);
1428 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
1430 ConstrainVarSubVar(from_vid, to_vid) => {
1431 let opp_vid = if from_vid == source_vid {
1436 if state.set.insert(opp_vid) {
1437 state.stack.push(opp_vid);
1441 ConstrainRegSubVar(region, _) |
1442 ConstrainVarSubReg(_, region) => {
1443 state.result.push(RegionAndOrigin {
1445 origin: this.constraints.borrow().get(&edge.data).unwrap().clone(),
1449 ConstrainRegSubReg(..) => {
1450 panic!("cannot reach reg-sub-reg edge in region inference \
1458 fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
1459 where F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool
1461 let mut iteration = 0;
1462 let mut changed = true;
1466 debug!("---- {} Iteration {}{}", "#", tag, iteration);
1467 for (constraint, origin) in self.constraints.borrow().iter() {
1468 let edge_changed = body(constraint, origin);
1470 debug!("Updated due to constraint {:?}", constraint);
1475 debug!("---- {} Complete after {} iteration(s)", tag, iteration);
1480 fn normalize<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1481 values: &Vec<VarValue<'tcx>>,
1482 r: ty::Region<'tcx>)
1483 -> ty::Region<'tcx> {
1485 ty::ReVar(rid) => lookup(tcx, values, rid),
1490 fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1491 values: &Vec<VarValue<'tcx>>,
1493 -> ty::Region<'tcx> {
1494 match values[rid.index as usize] {
1496 ErrorValue => tcx.types.re_static, // Previously reported error.
1500 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
1501 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1502 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
1506 impl fmt::Debug for RegionSnapshot {
1507 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1508 write!(f, "RegionSnapshot(length={},skolemization={})",
1509 self.length, self.skolemization_count)
1513 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
1514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1516 GenericKind::Param(ref p) => write!(f, "{:?}", p),
1517 GenericKind::Projection(ref p) => write!(f, "{:?}", p),
1522 impl<'tcx> fmt::Display for GenericKind<'tcx> {
1523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1525 GenericKind::Param(ref p) => write!(f, "{}", p),
1526 GenericKind::Projection(ref p) => write!(f, "{}", p),
1531 impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
1532 pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1534 GenericKind::Param(ref p) => p.to_ty(tcx),
1535 GenericKind::Projection(ref p) => tcx.mk_projection(p.trait_ref.clone(), p.item_name),
1540 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
1541 fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) {
1543 &VerifyBound::AnyRegion(ref rs) |
1544 &VerifyBound::AllRegions(ref rs) => for &r in rs {
1548 &VerifyBound::AnyBound(ref bs) |
1549 &VerifyBound::AllBounds(ref bs) => for b in bs {
1550 b.for_each_region(f);
1555 pub fn must_hold(&self) -> bool {
1557 &VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
1558 &VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1559 &VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1560 &VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1564 pub fn cannot_hold(&self) -> bool {
1566 &VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1567 &VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
1568 &VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1569 &VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1573 pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1574 if self.must_hold() || vb.cannot_hold() {
1576 } else if self.cannot_hold() || vb.must_hold() {
1579 VerifyBound::AnyBound(vec![self, vb])
1583 pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1584 if self.must_hold() && vb.must_hold() {
1586 } else if self.cannot_hold() && vb.cannot_hold() {
1589 VerifyBound::AllBounds(vec![self, vb])
1594 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1595 var_values: &Vec<VarValue<'tcx>>,
1596 min: ty::Region<'tcx>)
1598 let tcx = region_rels.tcx;
1600 &VerifyBound::AnyRegion(ref rs) =>
1602 .map(|&r| normalize(tcx, var_values, r))
1603 .any(|r| region_rels.is_subregion_of(min, r)),
1605 &VerifyBound::AllRegions(ref rs) =>
1607 .map(|&r| normalize(tcx, var_values, r))
1608 .all(|r| region_rels.is_subregion_of(min, r)),
1610 &VerifyBound::AnyBound(ref bs) =>
1612 .any(|b| b.is_met(region_rels, var_values, min)),
1614 &VerifyBound::AllBounds(ref bs) =>
1616 .all(|b| b.is_met(region_rels, var_values, min)),