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};
38 /// A constraint that influences the inference process.
39 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
40 pub enum Constraint<'tcx> {
41 /// One region variable is subregion of another
42 ConstrainVarSubVar(RegionVid, RegionVid),
44 /// Concrete region is subregion of region variable
45 ConstrainRegSubVar(Region<'tcx>, RegionVid),
47 /// Region variable is subregion of concrete region. This does not
48 /// directly affect inference, but instead is checked after
49 /// inference is complete.
50 ConstrainVarSubReg(RegionVid, Region<'tcx>),
52 /// A constraint where neither side is a variable. This does not
53 /// directly affect inference, but instead is checked after
54 /// inference is complete.
55 ConstrainRegSubReg(Region<'tcx>, Region<'tcx>),
58 /// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
59 /// associated type) must outlive the region `R`. `T` is known to
60 /// outlive `RS`. Therefore verify that `R <= RS[i]` for some
61 /// `i`. Inference variables may be involved (but this verification
62 /// step doesn't influence inference).
64 pub struct Verify<'tcx> {
65 kind: GenericKind<'tcx>,
66 origin: SubregionOrigin<'tcx>,
68 bound: VerifyBound<'tcx>,
71 #[derive(Copy, Clone, PartialEq, Eq)]
72 pub enum GenericKind<'tcx> {
74 Projection(ty::ProjectionTy<'tcx>),
77 /// When we introduce a verification step, we wish to test that a
78 /// particular region (let's call it `'min`) meets some bound.
79 /// The bound is described the by the following grammar:
81 pub enum VerifyBound<'tcx> {
82 /// B = exists {R} --> some 'r in {R} must outlive 'min
84 /// Put another way, the subject value is known to outlive all
85 /// regions in {R}, so if any of those outlives 'min, then the
87 AnyRegion(Vec<Region<'tcx>>),
89 /// B = forall {R} --> all 'r in {R} must outlive 'min
91 /// Put another way, the subject value is known to outlive some
92 /// region in {R}, so if all of those outlives 'min, then the bound
94 AllRegions(Vec<Region<'tcx>>),
96 /// B = exists {B} --> 'min must meet some bound b in {B}
97 AnyBound(Vec<VerifyBound<'tcx>>),
99 /// B = forall {B} --> 'min must meet all bounds b in {B}
100 AllBounds(Vec<VerifyBound<'tcx>>),
103 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
104 pub struct TwoRegions<'tcx> {
109 #[derive(Copy, Clone, PartialEq)]
110 pub enum UndoLogEntry<'tcx> {
111 /// Pushed when we start a snapshot.
114 /// Replaces an `OpenSnapshot` when a snapshot is committed, but
115 /// that snapshot is not the root. If the root snapshot is
116 /// unrolled, all nested snapshots must be committed.
119 /// We added `RegionVid`
122 /// We added the given `constraint`
123 AddConstraint(Constraint<'tcx>),
125 /// We added the given `verify`
128 /// We added the given `given`
129 AddGiven(Region<'tcx>, ty::RegionVid),
131 /// We added a GLB/LUB "combinaton variable"
132 AddCombination(CombineMapType, TwoRegions<'tcx>),
134 /// During skolemization, we sometimes purge entries from the undo
135 /// log in a kind of minisnapshot (unlike other snapshots, this
136 /// purging actually takes place *on success*). In that case, we
137 /// replace the corresponding entry with `Noop` so as to avoid the
138 /// need to do a bunch of swapping. (We can't use `swap_remove` as
139 /// the order of the vector is important.)
143 #[derive(Copy, Clone, PartialEq)]
144 pub enum CombineMapType {
149 #[derive(Clone, Debug)]
150 pub enum RegionResolutionError<'tcx> {
151 /// `ConcreteFailure(o, a, b)`:
153 /// `o` requires that `a <= b`, but this does not hold
154 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
156 /// `GenericBoundFailure(p, s, a)
158 /// The parameter/associated-type `p` must be known to outlive the lifetime
159 /// `a` (but none of the known bounds are sufficient).
160 GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>),
162 /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
164 /// Could not infer a value for `v` because `sub_r <= v` (due to
165 /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
166 /// `sub_r <= sup_r` does not hold.
167 SubSupConflict(RegionVariableOrigin,
168 SubregionOrigin<'tcx>,
170 SubregionOrigin<'tcx>,
174 #[derive(Clone, Debug)]
175 pub enum ProcessedErrorOrigin<'tcx> {
176 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
177 VariableFailure(RegionVariableOrigin),
180 pub type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
182 pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
183 tcx: TyCtxt<'a, 'gcx, 'tcx>,
184 var_origins: RefCell<Vec<RegionVariableOrigin>>,
186 /// Constraints of the form `A <= B` introduced by the region
187 /// checker. Here at least one of `A` and `B` must be a region
189 constraints: RefCell<FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
191 /// A "verify" is something that we need to verify after inference is
192 /// done, but which does not directly affect inference in any way.
194 /// An example is a `A <= B` where neither `A` nor `B` are
195 /// inference variables.
196 verifys: RefCell<Vec<Verify<'tcx>>>,
198 /// A "given" is a relationship that is known to hold. In particular,
199 /// we often know from closure fn signatures that a particular free
200 /// region must be a subregion of a region variable:
202 /// foo.iter().filter(<'a> |x: &'a &'b T| ...)
204 /// In situations like this, `'b` is in fact a region variable
205 /// introduced by the call to `iter()`, and `'a` is a bound region
206 /// on the closure (as indicated by the `<'a>` prefix). If we are
207 /// naive, we wind up inferring that `'b` must be `'static`,
208 /// because we require that it be greater than `'a` and we do not
209 /// know what `'a` is precisely.
211 /// This hashmap is used to avoid that naive scenario. Basically we
212 /// record the fact that `'a <= 'b` is implied by the fn signature,
213 /// and then ignore the constraint when solving equations. This is
214 /// a bit of a hack but seems to work.
215 givens: RefCell<FxHashSet<(Region<'tcx>, ty::RegionVid)>>,
217 lubs: RefCell<CombineMap<'tcx>>,
218 glbs: RefCell<CombineMap<'tcx>>,
219 skolemization_count: Cell<u32>,
220 bound_count: Cell<u32>,
222 /// The undo log records actions that might later be undone.
224 /// Note: when the undo_log is empty, we are not actively
225 /// snapshotting. When the `start_snapshot()` method is called, we
226 /// push an OpenSnapshot entry onto the list to indicate that we
227 /// are now actively snapshotting. The reason for this is that
228 /// otherwise we end up adding entries for things like the lower
229 /// bound on a variable and so forth, which can never be rolled
231 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(a, tcx.mk_region(ReVar(b)));
315 verifys[i].bound.for_each_region(&mut |b| {
316 self.add_edge(verifys[i].region, b);
320 &AddCombination(..) |
323 &CommitedSnapshot => {}
329 fn into_set(self) -> FxHashSet<ty::Region<'tcx>> {
333 fn len(&self) -> usize {
337 fn add_edge(&mut self,
338 source: ty::Region<'tcx>,
339 target: ty::Region<'tcx>) {
340 if self.directions.incoming {
341 if self.regions.contains(&target) {
342 self.regions.insert(source);
346 if self.directions.outgoing {
347 if self.regions.contains(&source) {
348 self.regions.insert(target);
354 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
355 pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
358 var_origins: RefCell::new(Vec::new()),
359 values: RefCell::new(None),
360 constraints: RefCell::new(FxHashMap()),
361 verifys: RefCell::new(Vec::new()),
362 givens: RefCell::new(FxHashSet()),
363 lubs: RefCell::new(FxHashMap()),
364 glbs: RefCell::new(FxHashMap()),
365 skolemization_count: Cell::new(0),
366 bound_count: Cell::new(0),
367 undo_log: RefCell::new(Vec::new()),
368 unification_table: RefCell::new(UnificationTable::new()),
372 fn in_snapshot(&self) -> bool {
373 !self.undo_log.borrow().is_empty()
376 pub fn start_snapshot(&self) -> RegionSnapshot {
377 let length = self.undo_log.borrow().len();
378 debug!("RegionVarBindings: start_snapshot({})", length);
379 self.undo_log.borrow_mut().push(OpenSnapshot);
382 region_snapshot: self.unification_table.borrow_mut().snapshot(),
383 skolemization_count: self.skolemization_count.get(),
387 pub fn commit(&self, snapshot: RegionSnapshot) {
388 debug!("RegionVarBindings: commit({})", snapshot.length);
389 assert!(self.undo_log.borrow().len() > snapshot.length);
390 assert!((*self.undo_log.borrow())[snapshot.length] == OpenSnapshot);
391 assert!(self.skolemization_count.get() == snapshot.skolemization_count,
392 "failed to pop skolemized regions: {} now vs {} at start",
393 self.skolemization_count.get(),
394 snapshot.skolemization_count);
396 let mut undo_log = self.undo_log.borrow_mut();
397 if snapshot.length == 0 {
398 undo_log.truncate(0);
400 (*undo_log)[snapshot.length] = CommitedSnapshot;
402 self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
405 pub fn rollback_to(&self, snapshot: RegionSnapshot) {
406 debug!("RegionVarBindings: rollback_to({:?})", snapshot);
407 let mut undo_log = self.undo_log.borrow_mut();
408 assert!(undo_log.len() > snapshot.length);
409 assert!((*undo_log)[snapshot.length] == OpenSnapshot);
410 while undo_log.len() > snapshot.length + 1 {
411 self.rollback_undo_entry(undo_log.pop().unwrap());
413 let c = undo_log.pop().unwrap();
414 assert!(c == OpenSnapshot);
415 self.skolemization_count.set(snapshot.skolemization_count);
416 self.unification_table.borrow_mut()
417 .rollback_to(snapshot.region_snapshot);
420 pub fn rollback_undo_entry(&self, undo_entry: UndoLogEntry<'tcx>) {
423 panic!("Failure to observe stack discipline");
425 Purged | CommitedSnapshot => {
426 // nothing to do here
429 let mut var_origins = self.var_origins.borrow_mut();
430 var_origins.pop().unwrap();
431 assert_eq!(var_origins.len(), vid.index as usize);
433 AddConstraint(ref constraint) => {
434 self.constraints.borrow_mut().remove(constraint);
436 AddVerify(index) => {
437 self.verifys.borrow_mut().pop();
438 assert_eq!(self.verifys.borrow().len(), index);
440 AddGiven(sub, sup) => {
441 self.givens.borrow_mut().remove(&(sub, sup));
443 AddCombination(Glb, ref regions) => {
444 self.glbs.borrow_mut().remove(regions);
446 AddCombination(Lub, ref regions) => {
447 self.lubs.borrow_mut().remove(regions);
452 pub fn num_vars(&self) -> u32 {
453 let len = self.var_origins.borrow().len();
454 // enforce no overflow
455 assert!(len as u32 as usize == len);
459 pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
460 let vid = RegionVid { index: self.num_vars() };
461 self.var_origins.borrow_mut().push(origin.clone());
463 let u_vid = self.unification_table.borrow_mut().new_key(
464 unify_key::RegionVidKey { min_vid: vid }
466 assert_eq!(vid, u_vid);
467 if self.in_snapshot() {
468 self.undo_log.borrow_mut().push(AddVar(vid));
470 debug!("created new region variable {:?} with origin {:?}",
476 pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
477 self.var_origins.borrow()[vid.index as usize].clone()
480 /// Creates a new skolemized region. Skolemized regions are fresh
481 /// regions used when performing higher-ranked computations. They
482 /// must be used in a very particular way and are never supposed
483 /// to "escape" out into error messages or the code at large.
485 /// The idea is to always create a snapshot. Skolemized regions
486 /// can be created in the context of this snapshot, but before the
487 /// snapshot is committed or rolled back, they must be popped
488 /// (using `pop_skolemized_regions`), so that their numbers can be
489 /// recycled. Normally you don't have to think about this: you use
490 /// the APIs in `higher_ranked/mod.rs`, such as
491 /// `skolemize_late_bound_regions` and `plug_leaks`, which will
492 /// guide you on this path (ensure that the `SkolemizationMap` is
493 /// consumed and you are good). There are also somewhat extensive
494 /// comments in `higher_ranked/README.md`.
496 /// The `snapshot` argument to this function is not really used;
497 /// it's just there to make it explicit which snapshot bounds the
498 /// skolemized region that results. It should always be the top-most snapshot.
499 pub fn push_skolemized(&self, br: ty::BoundRegion, snapshot: &RegionSnapshot)
501 assert!(self.in_snapshot());
502 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
504 let sc = self.skolemization_count.get();
505 self.skolemization_count.set(sc + 1);
506 self.tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
509 /// Removes all the edges to/from the skolemized regions that are
510 /// in `skols`. This is used after a higher-ranked operation
511 /// completes to remove all trace of the skolemized regions
512 /// created in that time.
513 pub fn pop_skolemized(&self,
514 skols: &FxHashSet<ty::Region<'tcx>>,
515 snapshot: &RegionSnapshot) {
516 debug!("pop_skolemized_regions(skols={:?})", skols);
518 assert!(self.in_snapshot());
519 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
520 assert!(self.skolemization_count.get() as usize >= skols.len(),
521 "popping more skolemized variables than actually exist, \
522 sc now = {}, skols.len = {}",
523 self.skolemization_count.get(),
526 let last_to_pop = self.skolemization_count.get();
527 let first_to_pop = last_to_pop - (skols.len() as u32);
529 assert!(first_to_pop >= snapshot.skolemization_count,
530 "popping more regions than snapshot contains, \
531 sc now = {}, sc then = {}, skols.len = {}",
532 self.skolemization_count.get(),
533 snapshot.skolemization_count,
538 ty::ReSkolemized(index, _) =>
539 index.index >= first_to_pop &&
540 index.index < last_to_pop,
544 "invalid skolemization keys or keys out of range ({}..{}): {:?}",
545 snapshot.skolemization_count,
546 self.skolemization_count.get(),
550 let mut undo_log = self.undo_log.borrow_mut();
552 let constraints_to_kill: Vec<usize> =
556 .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry))
557 .map(|(index, _)| index)
560 for index in constraints_to_kill {
561 let undo_entry = mem::replace(&mut undo_log[index], Purged);
562 self.rollback_undo_entry(undo_entry);
565 self.skolemization_count.set(snapshot.skolemization_count);
568 fn kill_constraint<'tcx>(skols: &FxHashSet<ty::Region<'tcx>>,
569 undo_entry: &UndoLogEntry<'tcx>)
572 &AddConstraint(ConstrainVarSubVar(..)) =>
574 &AddConstraint(ConstrainRegSubVar(a, _)) =>
576 &AddConstraint(ConstrainVarSubReg(_, b)) =>
578 &AddConstraint(ConstrainRegSubReg(a, b)) =>
579 skols.contains(&a) || skols.contains(&b),
584 &AddCombination(_, ref two_regions) =>
585 skols.contains(&two_regions.a) ||
586 skols.contains(&two_regions.b),
597 pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> Region<'tcx> {
598 // Creates a fresh bound variable for use in GLB computations.
599 // See discussion of GLB computation in the large comment at
600 // the top of this file for more details.
602 // This computation is potentially wrong in the face of
603 // rollover. It's conceivable, if unlikely, that one might
604 // wind up with accidental capture for nested functions in
605 // that case, if the outer function had bound regions created
606 // a very long time before and the inner function somehow
607 // wound up rolling over such that supposedly fresh
608 // identifiers were in fact shadowed. For now, we just assert
609 // that there is no rollover -- eventually we should try to be
610 // robust against this possibility, either by checking the set
611 // of bound identifiers that appear in a given expression and
612 // ensure that we generate one that is distinct, or by
613 // changing the representation of bound regions in a fn
616 let sc = self.bound_count.get();
617 self.bound_count.set(sc + 1);
619 if sc >= self.bound_count.get() {
620 bug!("rollover in RegionInference new_bound()");
623 self.tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
626 fn values_are_none(&self) -> bool {
627 self.values.borrow().is_none()
630 fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
631 // cannot add constraints once regions are resolved
632 assert!(self.values_are_none());
634 debug!("RegionVarBindings: add_constraint({:?})", constraint);
636 if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
637 if self.in_snapshot() {
638 self.undo_log.borrow_mut().push(AddConstraint(constraint));
643 fn add_verify(&self, verify: Verify<'tcx>) {
644 // cannot add verifys once regions are resolved
645 assert!(self.values_are_none());
647 debug!("RegionVarBindings: add_verify({:?})", verify);
649 // skip no-op cases known to be satisfied
651 VerifyBound::AllBounds(ref bs) if bs.len() == 0 => { return; }
655 let mut verifys = self.verifys.borrow_mut();
656 let index = verifys.len();
657 verifys.push(verify);
658 if self.in_snapshot() {
659 self.undo_log.borrow_mut().push(AddVerify(index));
663 pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
664 // cannot add givens once regions are resolved
665 assert!(self.values_are_none());
667 let mut givens = self.givens.borrow_mut();
668 if givens.insert((sub, sup)) {
669 debug!("add_given({:?} <= {:?})", sub, sup);
671 self.undo_log.borrow_mut().push(AddGiven(sub, sup));
675 pub fn make_eqregion(&self,
676 origin: SubregionOrigin<'tcx>,
680 // Eventually, it would be nice to add direct support for
682 self.make_subregion(origin.clone(), sub, sup);
683 self.make_subregion(origin, sup, sub);
685 if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
686 self.unification_table.borrow_mut().union(sub, sup);
691 pub fn make_subregion(&self,
692 origin: SubregionOrigin<'tcx>,
695 // cannot add constraints once regions are resolved
696 assert!(self.values_are_none());
698 debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
704 (&ReLateBound(..), _) |
705 (_, &ReLateBound(..)) => {
706 span_bug!(origin.span(),
707 "cannot relate bound region: {:?} <= {:?}",
712 // all regions are subregions of static, so we can ignore this
714 (&ReVar(sub_id), &ReVar(sup_id)) => {
715 self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
717 (_, &ReVar(sup_id)) => {
718 self.add_constraint(ConstrainRegSubVar(sub, sup_id), origin);
720 (&ReVar(sub_id), _) => {
721 self.add_constraint(ConstrainVarSubReg(sub_id, sup), origin);
724 self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
729 /// See `Verify::VerifyGenericBound`
730 pub fn verify_generic_bound(&self,
731 origin: SubregionOrigin<'tcx>,
732 kind: GenericKind<'tcx>,
734 bound: VerifyBound<'tcx>) {
735 self.add_verify(Verify {
743 pub fn lub_regions(&self,
744 origin: SubregionOrigin<'tcx>,
748 // cannot add constraints once regions are resolved
749 assert!(self.values_are_none());
751 debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b);
753 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
754 r // nothing lives longer than static
762 self.combine_vars(Lub, a, b, origin.clone(), |this, old_r, new_r| {
763 this.make_subregion(origin.clone(), old_r, new_r)
769 pub fn glb_regions(&self,
770 origin: SubregionOrigin<'tcx>,
774 // cannot add constraints once regions are resolved
775 assert!(self.values_are_none());
777 debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b);
779 (&ReStatic, r) | (r, &ReStatic) => {
780 r // static lives longer than everything else
788 self.combine_vars(Glb, a, b, origin.clone(), |this, old_r, new_r| {
789 this.make_subregion(origin.clone(), new_r, old_r)
795 pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
796 match *self.values.borrow() {
798 span_bug!((*self.var_origins.borrow())[rid.index as usize].span(),
799 "attempt to resolve region variable before values have \
802 Some(ref values) => {
803 let r = lookup(self.tcx, values, rid);
804 debug!("resolve_var({:?}) = {:?}", rid, r);
810 pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
811 let vid = self.unification_table.borrow_mut().find_value(rid).min_vid;
812 self.tcx.mk_region(ty::ReVar(vid))
815 fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap<'tcx>> {
822 pub fn combine_vars<F>(&self,
826 origin: SubregionOrigin<'tcx>,
829 where F: FnMut(&RegionVarBindings<'a, 'gcx, 'tcx>, Region<'tcx>, Region<'tcx>)
831 let vars = TwoRegions { a: a, b: b };
832 if let Some(&c) = self.combine_map(t).borrow().get(&vars) {
833 return self.tcx.mk_region(ReVar(c));
835 let c = self.new_region_var(MiscVariable(origin.span()));
836 self.combine_map(t).borrow_mut().insert(vars, c);
837 if self.in_snapshot() {
838 self.undo_log.borrow_mut().push(AddCombination(t, vars));
840 relate(self, a, self.tcx.mk_region(ReVar(c)));
841 relate(self, b, self.tcx.mk_region(ReVar(c)));
842 debug!("combine_vars() c={:?}", c);
843 self.tcx.mk_region(ReVar(c))
846 pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
847 self.undo_log.borrow()[mark.length..]
851 AddVar(vid) => Some(vid),
858 /// Computes all regions that have been related to `r0` since the
859 /// mark `mark` was made---`r0` itself will be the first
860 /// entry. The `directions` parameter controls what kind of
861 /// relations are considered. For example, one can say that only
862 /// "incoming" edges to `r0` are desired, in which case one will
863 /// get the set of regions `{r|r <= r0}`. This is used when
864 /// checking whether skolemized regions are being improperly
865 /// related to other regions.
866 pub fn tainted(&self,
867 mark: &RegionSnapshot,
869 directions: TaintDirections)
870 -> FxHashSet<ty::Region<'tcx>> {
871 debug!("tainted(mark={:?}, r0={:?}, directions={:?})",
872 mark, r0, directions);
874 // `result_set` acts as a worklist: we explore all outgoing
875 // edges and add any new regions we find to result_set. This
876 // is not a terribly efficient implementation.
877 let mut taint_set = TaintSet::new(directions, r0);
878 taint_set.fixed_point(self.tcx,
879 &self.undo_log.borrow()[mark.length..],
880 &self.verifys.borrow());
881 debug!("tainted: result={:?}", taint_set.regions);
882 return taint_set.into_set();
885 /// This function performs the actual region resolution. It must be
886 /// called after all constraints have been added. It performs a
887 /// fixed-point iteration to find region values which satisfy all
888 /// constraints, assuming such values can be found; if they cannot,
889 /// errors are reported.
890 pub fn resolve_regions(&self,
891 region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
892 -> Vec<RegionResolutionError<'tcx>> {
893 debug!("RegionVarBindings: resolve_regions()");
894 let mut errors = vec![];
895 let v = self.infer_variable_values(region_rels, &mut errors);
896 *self.values.borrow_mut() = Some(v);
900 fn lub_concrete_regions(&self,
901 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
906 (&ReLateBound(..), _) |
907 (_, &ReLateBound(..)) |
910 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
913 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
914 r // nothing lives longer than static
917 (&ReEmpty, r) | (r, &ReEmpty) => {
918 r // everything lives longer than empty
921 (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
922 span_bug!((*self.var_origins.borrow())[v_id.index as usize].span(),
923 "lub_concrete_regions invoked with non-concrete \
924 regions: {:?}, {:?}",
929 (&ReEarlyBound(_), &ReScope(s_id)) |
930 (&ReScope(s_id), &ReEarlyBound(_)) |
931 (&ReFree(_), &ReScope(s_id)) |
932 (&ReScope(s_id), &ReFree(_)) => {
933 // A "free" region can be interpreted as "some region
934 // at least as big as fr.scope". So, we can
935 // reasonably compare free regions and scopes:
936 let fr_scope = match (a, b) {
937 (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
938 region_rels.region_maps.early_free_extent(self.tcx, br)
940 (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
941 region_rels.region_maps.free_extent(self.tcx, fr)
945 let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
946 if r_id == fr_scope {
947 // if the free region's scope `fr.scope` is bigger than
948 // the scope region `s_id`, then the LUB is the free
951 (_, &ReScope(_)) => return a,
952 (&ReScope(_), _) => return b,
957 // otherwise, we don't know what the free region is,
958 // so we must conservatively say the LUB is static:
959 self.tcx.types.re_static
962 (&ReScope(a_id), &ReScope(b_id)) => {
963 // The region corresponding to an outer block is a
964 // subtype of the region corresponding to an inner
966 let lub = region_rels.region_maps.nearest_common_ancestor(a_id, b_id);
967 self.tcx.mk_region(ReScope(lub))
970 (&ReEarlyBound(_), &ReEarlyBound(_)) |
971 (&ReFree(_), &ReEarlyBound(_)) |
972 (&ReEarlyBound(_), &ReFree(_)) |
973 (&ReFree(_), &ReFree(_)) => {
974 region_rels.lub_free_regions(a, b)
977 // For these types, we cannot define any additional
979 (&ReSkolemized(..), _) |
980 (_, &ReSkolemized(..)) => {
984 self.tcx.types.re_static
991 // ______________________________________________________________________
993 #[derive(Copy, Clone, Debug)]
994 pub enum VarValue<'tcx> {
999 struct RegionAndOrigin<'tcx> {
1000 region: Region<'tcx>,
1001 origin: SubregionOrigin<'tcx>,
1004 type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
1006 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
1007 fn infer_variable_values(&self,
1008 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1009 errors: &mut Vec<RegionResolutionError<'tcx>>)
1010 -> Vec<VarValue<'tcx>> {
1011 let mut var_data = self.construct_var_data();
1013 // Dorky hack to cause `dump_constraints` to only get called
1014 // if debug mode is enabled:
1015 debug!("----() End constraint listing (context={:?}) {:?}---",
1016 region_rels.context,
1017 self.dump_constraints(region_rels));
1018 graphviz::maybe_print_constraints_for(self, region_rels);
1020 let graph = self.construct_graph();
1021 self.expand_givens(&graph);
1022 self.expansion(region_rels, &mut var_data);
1023 self.collect_errors(region_rels, &mut var_data, errors);
1024 self.collect_var_errors(region_rels, &var_data, &graph, errors);
1028 fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
1029 (0..self.num_vars() as usize)
1030 .map(|_| Value(self.tcx.types.re_empty))
1034 fn dump_constraints(&self, free_regions: &RegionRelations<'a, 'gcx, 'tcx>) {
1035 debug!("----() Start constraint listing (context={:?}) ()----",
1036 free_regions.context);
1037 for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
1038 debug!("Constraint {} => {:?}", idx, constraint);
1042 fn expand_givens(&self, graph: &RegionGraph) {
1043 // Givens are a kind of horrible hack to account for
1044 // constraints like 'c <= '0 that are known to hold due to
1045 // closure signatures (see the comment above on the `givens`
1046 // field). They should go away. But until they do, the role
1047 // of this fn is to account for the transitive nature:
1053 let mut givens = self.givens.borrow_mut();
1054 let seeds: Vec<_> = givens.iter().cloned().collect();
1055 for (r, vid) in seeds {
1056 let seed_index = NodeIndex(vid.index as usize);
1057 for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
1058 let succ_index = succ_index.0 as u32;
1059 if succ_index < self.num_vars() {
1060 let succ_vid = RegionVid { index: succ_index };
1061 givens.insert((r, succ_vid));
1068 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1069 var_values: &mut [VarValue<'tcx>]) {
1070 self.iterate_until_fixed_point("Expansion", |constraint, origin| {
1071 debug!("expansion: constraint={:?} origin={:?}",
1072 constraint, origin);
1074 ConstrainRegSubVar(a_region, b_vid) => {
1075 let b_data = &mut var_values[b_vid.index as usize];
1076 self.expand_node(region_rels, a_region, b_vid, b_data)
1078 ConstrainVarSubVar(a_vid, b_vid) => {
1079 match var_values[a_vid.index as usize] {
1080 ErrorValue => false,
1081 Value(a_region) => {
1082 let b_node = &mut var_values[b_vid.index as usize];
1083 self.expand_node(region_rels, a_region, b_vid, b_node)
1087 ConstrainRegSubReg(..) |
1088 ConstrainVarSubReg(..) => {
1089 // These constraints are checked after expansion
1090 // is done, in `collect_errors`.
1097 fn expand_node(&self,
1098 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1099 a_region: Region<'tcx>,
1101 b_data: &mut VarValue<'tcx>)
1103 debug!("expand_node({:?}, {:?} == {:?})",
1108 // Check if this relationship is implied by a given.
1110 ty::ReEarlyBound(_) |
1112 if self.givens.borrow().contains(&(a_region, b_vid)) {
1121 Value(cur_region) => {
1122 let lub = self.lub_concrete_regions(region_rels, a_region, cur_region);
1123 if lub == cur_region {
1127 debug!("Expanding value of {:?} from {:?} to {:?}",
1132 *b_data = Value(lub);
1142 /// After expansion is complete, go and check upper bounds (i.e.,
1143 /// cases where the region cannot grow larger than a fixed point)
1144 /// and check that they are satisfied.
1145 fn collect_errors(&self,
1146 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1147 var_data: &mut Vec<VarValue<'tcx>>,
1148 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1149 let constraints = self.constraints.borrow();
1150 for (constraint, origin) in constraints.iter() {
1151 debug!("collect_errors: constraint={:?} origin={:?}",
1152 constraint, origin);
1154 ConstrainRegSubVar(..) |
1155 ConstrainVarSubVar(..) => {
1156 // Expansion will ensure that these constraints hold. Ignore.
1159 ConstrainRegSubReg(sub, sup) => {
1160 if region_rels.is_subregion_of(sub, sup) {
1164 debug!("collect_errors: region error at {:?}: \
1165 cannot verify that {:?} <= {:?}",
1170 errors.push(ConcreteFailure((*origin).clone(), sub, sup));
1173 ConstrainVarSubReg(a_vid, b_region) => {
1174 let a_data = &mut var_data[a_vid.index as usize];
1175 debug!("contraction: {:?} == {:?}, {:?}",
1180 let a_region = match *a_data {
1181 ErrorValue => continue,
1182 Value(a_region) => a_region,
1185 // Do not report these errors immediately:
1186 // instead, set the variable value to error and
1187 // collect them later.
1188 if !region_rels.is_subregion_of(a_region, b_region) {
1189 debug!("collect_errors: region error at {:?}: \
1190 cannot verify that {:?}={:?} <= {:?}",
1195 *a_data = ErrorValue;
1201 for verify in self.verifys.borrow().iter() {
1202 debug!("collect_errors: verify={:?}", verify);
1203 let sub = normalize(self.tcx, var_data, verify.region);
1204 if verify.bound.is_met(region_rels, var_data, sub) {
1208 debug!("collect_errors: region error at {:?}: \
1209 cannot verify that {:?} <= {:?}",
1214 errors.push(GenericBoundFailure(verify.origin.clone(),
1215 verify.kind.clone(),
1220 /// Go over the variables that were declared to be error variables
1221 /// and create a `RegionResolutionError` for each of them.
1222 fn collect_var_errors(&self,
1223 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1224 var_data: &[VarValue<'tcx>],
1225 graph: &RegionGraph<'tcx>,
1226 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1227 debug!("collect_var_errors");
1229 // This is the best way that I have found to suppress
1230 // duplicate and related errors. Basically we keep a set of
1231 // flags for every node. Whenever an error occurs, we will
1232 // walk some portion of the graph looking to find pairs of
1233 // conflicting regions to report to the user. As we walk, we
1234 // trip the flags from false to true, and if we find that
1235 // we've already reported an error involving any particular
1236 // node we just stop and don't report the current error. The
1237 // idea is to report errors that derive from independent
1238 // regions of the graph, but not those that derive from
1239 // overlapping locations.
1240 let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
1242 for idx in 0..self.num_vars() as usize {
1243 match var_data[idx] {
1245 /* Inference successful */
1248 /* Inference impossible, this value contains
1249 inconsistent constraints.
1251 I think that in this case we should report an
1252 error now---unlike the case above, we can't
1253 wait to see whether the user needs the result
1254 of this variable. The reason is that the mere
1255 existence of this variable implies that the
1256 region graph is inconsistent, whether or not it
1259 For example, we may have created a region
1260 variable that is the GLB of two other regions
1261 which do not have a GLB. Even if that variable
1262 is not used, it implies that those two regions
1263 *should* have a GLB.
1265 At least I think this is true. It may be that
1266 the mere existence of a conflict in a region variable
1267 that is not used is not a problem, so if this rule
1268 starts to create problems we'll have to revisit
1269 this portion of the code and think hard about it. =) */
1271 let node_vid = RegionVid { index: idx as u32 };
1272 self.collect_error_for_expanding_node(region_rels,
1282 fn construct_graph(&self) -> RegionGraph<'tcx> {
1283 let num_vars = self.num_vars();
1285 let constraints = self.constraints.borrow();
1287 let mut graph = graph::Graph::new();
1289 for _ in 0..num_vars {
1293 // Issue #30438: two distinct dummy nodes, one for incoming
1294 // edges (dummy_source) and another for outgoing edges
1295 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
1296 // dummy node leads one to think (erroneously) there exists a
1297 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
1298 let dummy_source = graph.add_node(());
1299 let dummy_sink = graph.add_node(());
1301 for (constraint, _) in constraints.iter() {
1303 ConstrainVarSubVar(a_id, b_id) => {
1304 graph.add_edge(NodeIndex(a_id.index as usize),
1305 NodeIndex(b_id.index as usize),
1308 ConstrainRegSubVar(_, b_id) => {
1309 graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
1311 ConstrainVarSubReg(a_id, _) => {
1312 graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
1314 ConstrainRegSubReg(..) => {
1315 // this would be an edge from `dummy_source` to
1316 // `dummy_sink`; just ignore it.
1324 fn collect_error_for_expanding_node(&self,
1325 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1326 graph: &RegionGraph<'tcx>,
1327 dup_vec: &mut [u32],
1328 node_idx: RegionVid,
1329 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1330 // Errors in expanding nodes result from a lower-bound that is
1331 // not contained by an upper-bound.
1332 let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph,
1336 let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph,
1341 if lower_dup || upper_dup {
1345 // We place free regions first because we are special casing
1346 // SubSupConflict(ReFree, ReFree) when reporting error, and so
1347 // the user will more likely get a specific suggestion.
1348 fn region_order_key(x: &RegionAndOrigin) -> u8 {
1350 ReEarlyBound(_) => 0,
1355 lower_bounds.sort_by_key(region_order_key);
1356 upper_bounds.sort_by_key(region_order_key);
1358 for lower_bound in &lower_bounds {
1359 for upper_bound in &upper_bounds {
1360 if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
1361 let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1362 debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
1367 upper_bound.region);
1368 errors.push(SubSupConflict(origin,
1369 lower_bound.origin.clone(),
1371 upper_bound.origin.clone(),
1372 upper_bound.region));
1378 span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
1379 "collect_error_for_expanding_node() could not find \
1380 error for var {:?}, lower_bounds={:?}, \
1387 fn collect_concrete_regions(&self,
1388 graph: &RegionGraph<'tcx>,
1389 orig_node_idx: RegionVid,
1391 dup_vec: &mut [u32])
1392 -> (Vec<RegionAndOrigin<'tcx>>, bool) {
1393 struct WalkState<'tcx> {
1394 set: FxHashSet<RegionVid>,
1395 stack: Vec<RegionVid>,
1396 result: Vec<RegionAndOrigin<'tcx>>,
1399 let mut state = WalkState {
1401 stack: vec![orig_node_idx],
1405 state.set.insert(orig_node_idx);
1407 // to start off the process, walk the source node in the
1408 // direction specified
1409 process_edges(self, &mut state, graph, orig_node_idx, dir);
1411 while !state.stack.is_empty() {
1412 let node_idx = state.stack.pop().unwrap();
1414 // check whether we've visited this node on some previous walk
1415 if dup_vec[node_idx.index as usize] == u32::MAX {
1416 dup_vec[node_idx.index as usize] = orig_node_idx.index;
1417 } else if dup_vec[node_idx.index as usize] != orig_node_idx.index {
1418 state.dup_found = true;
1421 debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
1425 process_edges(self, &mut state, graph, node_idx, dir);
1428 let WalkState {result, dup_found, ..} = state;
1429 return (result, dup_found);
1431 fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
1432 state: &mut WalkState<'tcx>,
1433 graph: &RegionGraph<'tcx>,
1434 source_vid: RegionVid,
1436 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
1438 let source_node_index = NodeIndex(source_vid.index as usize);
1439 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
1441 ConstrainVarSubVar(from_vid, to_vid) => {
1442 let opp_vid = if from_vid == source_vid {
1447 if state.set.insert(opp_vid) {
1448 state.stack.push(opp_vid);
1452 ConstrainRegSubVar(region, _) |
1453 ConstrainVarSubReg(_, region) => {
1454 state.result.push(RegionAndOrigin {
1456 origin: this.constraints.borrow().get(&edge.data).unwrap().clone(),
1460 ConstrainRegSubReg(..) => {
1461 panic!("cannot reach reg-sub-reg edge in region inference \
1469 fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
1470 where F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool
1472 let mut iteration = 0;
1473 let mut changed = true;
1477 debug!("---- {} Iteration {}{}", "#", tag, iteration);
1478 for (constraint, origin) in self.constraints.borrow().iter() {
1479 let edge_changed = body(constraint, origin);
1481 debug!("Updated due to constraint {:?}", constraint);
1486 debug!("---- {} Complete after {} iteration(s)", tag, iteration);
1491 fn normalize<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1492 values: &Vec<VarValue<'tcx>>,
1493 r: ty::Region<'tcx>)
1494 -> ty::Region<'tcx> {
1496 ty::ReVar(rid) => lookup(tcx, values, rid),
1501 fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1502 values: &Vec<VarValue<'tcx>>,
1504 -> ty::Region<'tcx> {
1505 match values[rid.index as usize] {
1507 ErrorValue => tcx.types.re_static, // Previously reported error.
1511 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
1512 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1513 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
1517 impl fmt::Debug for RegionSnapshot {
1518 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1519 write!(f, "RegionSnapshot(length={},skolemization={})",
1520 self.length, self.skolemization_count)
1524 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
1525 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1527 GenericKind::Param(ref p) => write!(f, "{:?}", p),
1528 GenericKind::Projection(ref p) => write!(f, "{:?}", p),
1533 impl<'tcx> fmt::Display for GenericKind<'tcx> {
1534 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1536 GenericKind::Param(ref p) => write!(f, "{}", p),
1537 GenericKind::Projection(ref p) => write!(f, "{}", p),
1542 impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
1543 pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1545 GenericKind::Param(ref p) => p.to_ty(tcx),
1546 GenericKind::Projection(ref p) => tcx.mk_projection(
1547 p.trait_ref.clone(), p.item_name(tcx)),
1552 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
1553 fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) {
1555 &VerifyBound::AnyRegion(ref rs) |
1556 &VerifyBound::AllRegions(ref rs) => for &r in rs {
1560 &VerifyBound::AnyBound(ref bs) |
1561 &VerifyBound::AllBounds(ref bs) => for b in bs {
1562 b.for_each_region(f);
1567 pub fn must_hold(&self) -> bool {
1569 &VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
1570 &VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1571 &VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1572 &VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1576 pub fn cannot_hold(&self) -> bool {
1578 &VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1579 &VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
1580 &VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1581 &VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1585 pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1586 if self.must_hold() || vb.cannot_hold() {
1588 } else if self.cannot_hold() || vb.must_hold() {
1591 VerifyBound::AnyBound(vec![self, vb])
1595 pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1596 if self.must_hold() && vb.must_hold() {
1598 } else if self.cannot_hold() && vb.cannot_hold() {
1601 VerifyBound::AllBounds(vec![self, vb])
1606 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1607 var_values: &Vec<VarValue<'tcx>>,
1608 min: ty::Region<'tcx>)
1610 let tcx = region_rels.tcx;
1612 &VerifyBound::AnyRegion(ref rs) =>
1614 .map(|&r| normalize(tcx, var_values, r))
1615 .any(|r| region_rels.is_subregion_of(min, r)),
1617 &VerifyBound::AllRegions(ref rs) =>
1619 .map(|&r| normalize(tcx, var_values, r))
1620 .all(|r| region_rels.is_subregion_of(min, r)),
1622 &VerifyBound::AnyBound(ref bs) =>
1624 .any(|b| b.is_met(region_rels, var_values, min)),
1626 &VerifyBound::AllBounds(ref bs) =>
1628 .all(|b| b.is_met(region_rels, var_values, min)),