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));
1056 fn expansion(&self, region_rels: &RegionRelations<'a, 'gcx, 'tcx>, var_values: &mut [VarValue<'tcx>]) {
1057 self.iterate_until_fixed_point("Expansion", |constraint, origin| {
1058 debug!("expansion: constraint={:?} origin={:?}",
1059 constraint, origin);
1061 ConstrainRegSubVar(a_region, b_vid) => {
1062 let b_data = &mut var_values[b_vid.index as usize];
1063 self.expand_node(region_rels, a_region, b_vid, b_data)
1065 ConstrainVarSubVar(a_vid, b_vid) => {
1066 match var_values[a_vid.index as usize] {
1067 ErrorValue => false,
1068 Value(a_region) => {
1069 let b_node = &mut var_values[b_vid.index as usize];
1070 self.expand_node(region_rels, a_region, b_vid, b_node)
1074 ConstrainRegSubReg(..) |
1075 ConstrainVarSubReg(..) => {
1076 // These constraints are checked after expansion
1077 // is done, in `collect_errors`.
1084 fn expand_node(&self,
1085 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1086 a_region: Region<'tcx>,
1088 b_data: &mut VarValue<'tcx>)
1090 debug!("expand_node({:?}, {:?} == {:?})",
1095 // Check if this relationship is implied by a given.
1098 if self.givens.borrow().contains(&(fr, b_vid)) {
1107 Value(cur_region) => {
1108 let lub = self.lub_concrete_regions(region_rels, a_region, cur_region);
1109 if lub == cur_region {
1113 debug!("Expanding value of {:?} from {:?} to {:?}",
1118 *b_data = Value(lub);
1128 /// After expansion is complete, go and check upper bounds (i.e.,
1129 /// cases where the region cannot grow larger than a fixed point)
1130 /// and check that they are satisfied.
1131 fn collect_errors(&self,
1132 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1133 var_data: &mut Vec<VarValue<'tcx>>,
1134 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1135 let constraints = self.constraints.borrow();
1136 for (constraint, origin) in constraints.iter() {
1137 debug!("collect_errors: constraint={:?} origin={:?}",
1138 constraint, origin);
1140 ConstrainRegSubVar(..) |
1141 ConstrainVarSubVar(..) => {
1142 // Expansion will ensure that these constraints hold. Ignore.
1145 ConstrainRegSubReg(sub, sup) => {
1146 if region_rels.is_subregion_of(sub, sup) {
1150 debug!("collect_errors: region error at {:?}: \
1151 cannot verify that {:?} <= {:?}",
1156 errors.push(ConcreteFailure((*origin).clone(), sub, sup));
1159 ConstrainVarSubReg(a_vid, b_region) => {
1160 let a_data = &mut var_data[a_vid.index as usize];
1161 debug!("contraction: {:?} == {:?}, {:?}",
1166 let a_region = match *a_data {
1167 ErrorValue => continue,
1168 Value(a_region) => a_region,
1171 // Do not report these errors immediately:
1172 // instead, set the variable value to error and
1173 // collect them later.
1174 if !region_rels.is_subregion_of(a_region, b_region) {
1175 debug!("collect_errors: region error at {:?}: \
1176 cannot verify that {:?}={:?} <= {:?}",
1181 *a_data = ErrorValue;
1187 for verify in self.verifys.borrow().iter() {
1188 debug!("collect_errors: verify={:?}", verify);
1189 let sub = normalize(self.tcx, var_data, verify.region);
1190 if verify.bound.is_met(region_rels, var_data, sub) {
1194 debug!("collect_errors: region error at {:?}: \
1195 cannot verify that {:?} <= {:?}",
1200 errors.push(GenericBoundFailure(verify.origin.clone(),
1201 verify.kind.clone(),
1206 /// Go over the variables that were declared to be error variables
1207 /// and create a `RegionResolutionError` for each of them.
1208 fn collect_var_errors(&self,
1209 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1210 var_data: &[VarValue<'tcx>],
1211 graph: &RegionGraph<'tcx>,
1212 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1213 debug!("collect_var_errors");
1215 // This is the best way that I have found to suppress
1216 // duplicate and related errors. Basically we keep a set of
1217 // flags for every node. Whenever an error occurs, we will
1218 // walk some portion of the graph looking to find pairs of
1219 // conflicting regions to report to the user. As we walk, we
1220 // trip the flags from false to true, and if we find that
1221 // we've already reported an error involving any particular
1222 // node we just stop and don't report the current error. The
1223 // idea is to report errors that derive from independent
1224 // regions of the graph, but not those that derive from
1225 // overlapping locations.
1226 let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
1228 for idx in 0..self.num_vars() as usize {
1229 match var_data[idx] {
1231 /* Inference successful */
1234 /* Inference impossible, this value contains
1235 inconsistent constraints.
1237 I think that in this case we should report an
1238 error now---unlike the case above, we can't
1239 wait to see whether the user needs the result
1240 of this variable. The reason is that the mere
1241 existence of this variable implies that the
1242 region graph is inconsistent, whether or not it
1245 For example, we may have created a region
1246 variable that is the GLB of two other regions
1247 which do not have a GLB. Even if that variable
1248 is not used, it implies that those two regions
1249 *should* have a GLB.
1251 At least I think this is true. It may be that
1252 the mere existence of a conflict in a region variable
1253 that is not used is not a problem, so if this rule
1254 starts to create problems we'll have to revisit
1255 this portion of the code and think hard about it. =) */
1257 let node_vid = RegionVid { index: idx as u32 };
1258 self.collect_error_for_expanding_node(region_rels,
1268 fn construct_graph(&self) -> RegionGraph<'tcx> {
1269 let num_vars = self.num_vars();
1271 let constraints = self.constraints.borrow();
1273 let mut graph = graph::Graph::new();
1275 for _ in 0..num_vars {
1279 // Issue #30438: two distinct dummy nodes, one for incoming
1280 // edges (dummy_source) and another for outgoing edges
1281 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
1282 // dummy node leads one to think (erroneously) there exists a
1283 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
1284 let dummy_source = graph.add_node(());
1285 let dummy_sink = graph.add_node(());
1287 for (constraint, _) in constraints.iter() {
1289 ConstrainVarSubVar(a_id, b_id) => {
1290 graph.add_edge(NodeIndex(a_id.index as usize),
1291 NodeIndex(b_id.index as usize),
1294 ConstrainRegSubVar(_, b_id) => {
1295 graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
1297 ConstrainVarSubReg(a_id, _) => {
1298 graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
1300 ConstrainRegSubReg(..) => {
1301 // this would be an edge from `dummy_source` to
1302 // `dummy_sink`; just ignore it.
1310 fn collect_error_for_expanding_node(&self,
1311 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1312 graph: &RegionGraph<'tcx>,
1313 dup_vec: &mut [u32],
1314 node_idx: RegionVid,
1315 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1316 // Errors in expanding nodes result from a lower-bound that is
1317 // not contained by an upper-bound.
1318 let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph,
1322 let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph,
1327 if lower_dup || upper_dup {
1331 // We place free regions first because we are special casing
1332 // SubSupConflict(ReFree, ReFree) when reporting error, and so
1333 // the user will more likely get a specific suggestion.
1334 fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
1335 match (a.region, b.region) {
1336 (&ReFree(..), &ReFree(..)) => Equal,
1337 (&ReFree(..), _) => Less,
1338 (_, &ReFree(..)) => Greater,
1342 lower_bounds.sort_by(|a, b| free_regions_first(a, b));
1343 upper_bounds.sort_by(|a, b| free_regions_first(a, b));
1345 for lower_bound in &lower_bounds {
1346 for upper_bound in &upper_bounds {
1347 if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
1348 let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1349 debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
1354 upper_bound.region);
1355 errors.push(SubSupConflict(origin,
1356 lower_bound.origin.clone(),
1358 upper_bound.origin.clone(),
1359 upper_bound.region));
1365 span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
1366 "collect_error_for_expanding_node() could not find \
1367 error for var {:?}, lower_bounds={:?}, \
1374 fn collect_concrete_regions(&self,
1375 graph: &RegionGraph<'tcx>,
1376 orig_node_idx: RegionVid,
1378 dup_vec: &mut [u32])
1379 -> (Vec<RegionAndOrigin<'tcx>>, bool) {
1380 struct WalkState<'tcx> {
1381 set: FxHashSet<RegionVid>,
1382 stack: Vec<RegionVid>,
1383 result: Vec<RegionAndOrigin<'tcx>>,
1386 let mut state = WalkState {
1388 stack: vec![orig_node_idx],
1392 state.set.insert(orig_node_idx);
1394 // to start off the process, walk the source node in the
1395 // direction specified
1396 process_edges(self, &mut state, graph, orig_node_idx, dir);
1398 while !state.stack.is_empty() {
1399 let node_idx = state.stack.pop().unwrap();
1401 // check whether we've visited this node on some previous walk
1402 if dup_vec[node_idx.index as usize] == u32::MAX {
1403 dup_vec[node_idx.index as usize] = orig_node_idx.index;
1404 } else if dup_vec[node_idx.index as usize] != orig_node_idx.index {
1405 state.dup_found = true;
1408 debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
1412 process_edges(self, &mut state, graph, node_idx, dir);
1415 let WalkState {result, dup_found, ..} = state;
1416 return (result, dup_found);
1418 fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
1419 state: &mut WalkState<'tcx>,
1420 graph: &RegionGraph<'tcx>,
1421 source_vid: RegionVid,
1423 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
1425 let source_node_index = NodeIndex(source_vid.index as usize);
1426 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
1428 ConstrainVarSubVar(from_vid, to_vid) => {
1429 let opp_vid = if from_vid == source_vid {
1434 if state.set.insert(opp_vid) {
1435 state.stack.push(opp_vid);
1439 ConstrainRegSubVar(region, _) |
1440 ConstrainVarSubReg(_, region) => {
1441 state.result.push(RegionAndOrigin {
1443 origin: this.constraints.borrow().get(&edge.data).unwrap().clone(),
1447 ConstrainRegSubReg(..) => {
1448 panic!("cannot reach reg-sub-reg edge in region inference \
1456 fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
1457 where F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool
1459 let mut iteration = 0;
1460 let mut changed = true;
1464 debug!("---- {} Iteration {}{}", "#", tag, iteration);
1465 for (constraint, origin) in self.constraints.borrow().iter() {
1466 let edge_changed = body(constraint, origin);
1468 debug!("Updated due to constraint {:?}", constraint);
1473 debug!("---- {} Complete after {} iteration(s)", tag, iteration);
1478 fn normalize<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1479 values: &Vec<VarValue<'tcx>>,
1480 r: ty::Region<'tcx>)
1481 -> ty::Region<'tcx> {
1483 ty::ReVar(rid) => lookup(tcx, values, rid),
1488 fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1489 values: &Vec<VarValue<'tcx>>,
1491 -> ty::Region<'tcx> {
1492 match values[rid.index as usize] {
1494 ErrorValue => tcx.types.re_static, // Previously reported error.
1498 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
1499 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1500 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
1504 impl fmt::Debug for RegionSnapshot {
1505 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1506 write!(f, "RegionSnapshot(length={},skolemization={})",
1507 self.length, self.skolemization_count)
1511 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
1512 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1514 GenericKind::Param(ref p) => write!(f, "{:?}", p),
1515 GenericKind::Projection(ref p) => write!(f, "{:?}", p),
1520 impl<'tcx> fmt::Display for GenericKind<'tcx> {
1521 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1523 GenericKind::Param(ref p) => write!(f, "{}", p),
1524 GenericKind::Projection(ref p) => write!(f, "{}", p),
1529 impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
1530 pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1532 GenericKind::Param(ref p) => p.to_ty(tcx),
1533 GenericKind::Projection(ref p) => tcx.mk_projection(p.trait_ref.clone(), p.item_name),
1538 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
1539 fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) {
1541 &VerifyBound::AnyRegion(ref rs) |
1542 &VerifyBound::AllRegions(ref rs) => for &r in rs {
1546 &VerifyBound::AnyBound(ref bs) |
1547 &VerifyBound::AllBounds(ref bs) => for b in bs {
1548 b.for_each_region(f);
1553 pub fn must_hold(&self) -> bool {
1555 &VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
1556 &VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1557 &VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1558 &VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1562 pub fn cannot_hold(&self) -> bool {
1564 &VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1565 &VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
1566 &VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1567 &VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1571 pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1572 if self.must_hold() || vb.cannot_hold() {
1574 } else if self.cannot_hold() || vb.must_hold() {
1577 VerifyBound::AnyBound(vec![self, vb])
1581 pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1582 if self.must_hold() && vb.must_hold() {
1584 } else if self.cannot_hold() && vb.cannot_hold() {
1587 VerifyBound::AllBounds(vec![self, vb])
1592 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1593 var_values: &Vec<VarValue<'tcx>>,
1594 min: ty::Region<'tcx>)
1596 let tcx = region_rels.tcx;
1598 &VerifyBound::AnyRegion(ref rs) =>
1600 .map(|&r| normalize(tcx, var_values, r))
1601 .any(|r| region_rels.is_subregion_of(min, r)),
1603 &VerifyBound::AllRegions(ref rs) =>
1605 .map(|&r| normalize(tcx, var_values, r))
1606 .all(|r| region_rels.is_subregion_of(min, r)),
1608 &VerifyBound::AnyBound(ref bs) =>
1610 .any(|b| b.is_met(region_rels, var_values, min)),
1612 &VerifyBound::AllBounds(ref bs) =>
1614 .all(|b| b.is_met(region_rels, var_values, min)),