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>>>,
232 unification_table: RefCell<UnificationTable<ty::RegionVid>>,
234 // This contains the results of inference. It begins as an empty
235 // option and only acquires a value after inference is complete.
236 values: RefCell<Option<Vec<VarValue<'tcx>>>>,
239 pub struct RegionSnapshot {
241 region_snapshot: unify::Snapshot<ty::RegionVid>,
242 skolemization_count: u32,
245 /// When working with skolemized regions, we often wish to find all of
246 /// the regions that are either reachable from a skolemized region, or
247 /// which can reach a skolemized region, or both. We call such regions
248 /// *tained* regions. This struct allows you to decide what set of
249 /// tainted regions you want.
251 pub struct TaintDirections {
256 impl TaintDirections {
257 pub fn incoming() -> Self {
258 TaintDirections { incoming: true, outgoing: false }
261 pub fn outgoing() -> Self {
262 TaintDirections { incoming: false, outgoing: true }
265 pub fn both() -> Self {
266 TaintDirections { incoming: true, outgoing: true }
270 struct TaintSet<'tcx> {
271 directions: TaintDirections,
272 regions: FxHashSet<ty::Region<'tcx>>
275 impl<'a, 'gcx, 'tcx> TaintSet<'tcx> {
276 fn new(directions: TaintDirections,
277 initial_region: ty::Region<'tcx>)
279 let mut regions = FxHashSet();
280 regions.insert(initial_region);
281 TaintSet { directions: directions, regions: regions }
284 fn fixed_point(&mut self,
285 tcx: TyCtxt<'a, 'gcx, 'tcx>,
286 undo_log: &[UndoLogEntry<'tcx>],
287 verifys: &[Verify<'tcx>]) {
288 let mut prev_len = 0;
289 while prev_len < self.len() {
290 debug!("tainted: prev_len = {:?} new_len = {:?}",
291 prev_len, self.len());
293 prev_len = self.len();
295 for undo_entry in undo_log {
297 &AddConstraint(ConstrainVarSubVar(a, b)) => {
298 self.add_edge(tcx.mk_region(ReVar(a)),
299 tcx.mk_region(ReVar(b)));
301 &AddConstraint(ConstrainRegSubVar(a, b)) => {
302 self.add_edge(a, tcx.mk_region(ReVar(b)));
304 &AddConstraint(ConstrainVarSubReg(a, b)) => {
305 self.add_edge(tcx.mk_region(ReVar(a)), b);
307 &AddConstraint(ConstrainRegSubReg(a, b)) => {
311 self.add_edge(a, tcx.mk_region(ReVar(b)));
314 verifys[i].bound.for_each_region(&mut |b| {
315 self.add_edge(verifys[i].region, b);
319 &AddCombination(..) |
322 &CommitedSnapshot => {}
328 fn into_set(self) -> FxHashSet<ty::Region<'tcx>> {
332 fn len(&self) -> usize {
336 fn add_edge(&mut self,
337 source: ty::Region<'tcx>,
338 target: ty::Region<'tcx>) {
339 if self.directions.incoming {
340 if self.regions.contains(&target) {
341 self.regions.insert(source);
345 if self.directions.outgoing {
346 if self.regions.contains(&source) {
347 self.regions.insert(target);
353 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
354 pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
357 var_origins: RefCell::new(Vec::new()),
358 values: RefCell::new(None),
359 constraints: RefCell::new(FxHashMap()),
360 verifys: RefCell::new(Vec::new()),
361 givens: RefCell::new(FxHashSet()),
362 lubs: RefCell::new(FxHashMap()),
363 glbs: RefCell::new(FxHashMap()),
364 skolemization_count: Cell::new(0),
365 bound_count: Cell::new(0),
366 undo_log: RefCell::new(Vec::new()),
367 unification_table: RefCell::new(UnificationTable::new()),
371 fn in_snapshot(&self) -> bool {
372 !self.undo_log.borrow().is_empty()
375 pub fn start_snapshot(&self) -> RegionSnapshot {
376 let length = self.undo_log.borrow().len();
377 debug!("RegionVarBindings: start_snapshot({})", length);
378 self.undo_log.borrow_mut().push(OpenSnapshot);
381 region_snapshot: self.unification_table.borrow_mut().snapshot(),
382 skolemization_count: self.skolemization_count.get(),
386 pub fn commit(&self, snapshot: RegionSnapshot) {
387 debug!("RegionVarBindings: commit({})", snapshot.length);
388 assert!(self.undo_log.borrow().len() > snapshot.length);
389 assert!((*self.undo_log.borrow())[snapshot.length] == OpenSnapshot);
390 assert!(self.skolemization_count.get() == snapshot.skolemization_count,
391 "failed to pop skolemized regions: {} now vs {} at start",
392 self.skolemization_count.get(),
393 snapshot.skolemization_count);
395 let mut undo_log = self.undo_log.borrow_mut();
396 if snapshot.length == 0 {
397 undo_log.truncate(0);
399 (*undo_log)[snapshot.length] = CommitedSnapshot;
401 self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
404 pub fn rollback_to(&self, snapshot: RegionSnapshot) {
405 debug!("RegionVarBindings: rollback_to({:?})", snapshot);
406 let mut undo_log = self.undo_log.borrow_mut();
407 assert!(undo_log.len() > snapshot.length);
408 assert!((*undo_log)[snapshot.length] == OpenSnapshot);
409 while undo_log.len() > snapshot.length + 1 {
410 self.rollback_undo_entry(undo_log.pop().unwrap());
412 let c = undo_log.pop().unwrap();
413 assert!(c == OpenSnapshot);
414 self.skolemization_count.set(snapshot.skolemization_count);
415 self.unification_table.borrow_mut()
416 .rollback_to(snapshot.region_snapshot);
419 pub fn rollback_undo_entry(&self, undo_entry: UndoLogEntry<'tcx>) {
422 panic!("Failure to observe stack discipline");
424 Purged | CommitedSnapshot => {
425 // nothing to do here
428 let mut var_origins = self.var_origins.borrow_mut();
429 var_origins.pop().unwrap();
430 assert_eq!(var_origins.len(), vid.index as usize);
432 AddConstraint(ref constraint) => {
433 self.constraints.borrow_mut().remove(constraint);
435 AddVerify(index) => {
436 self.verifys.borrow_mut().pop();
437 assert_eq!(self.verifys.borrow().len(), index);
439 AddGiven(sub, sup) => {
440 self.givens.borrow_mut().remove(&(sub, sup));
442 AddCombination(Glb, ref regions) => {
443 self.glbs.borrow_mut().remove(regions);
445 AddCombination(Lub, ref regions) => {
446 self.lubs.borrow_mut().remove(regions);
451 pub fn num_vars(&self) -> u32 {
452 let len = self.var_origins.borrow().len();
453 // enforce no overflow
454 assert!(len as u32 as usize == len);
458 pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
459 let vid = RegionVid { index: self.num_vars() };
460 self.var_origins.borrow_mut().push(origin.clone());
462 let u_vid = self.unification_table.borrow_mut().new_key(
463 unify_key::RegionVidKey { min_vid: vid }
465 assert_eq!(vid, u_vid);
466 if self.in_snapshot() {
467 self.undo_log.borrow_mut().push(AddVar(vid));
469 debug!("created new region variable {:?} with origin {:?}",
475 pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
476 self.var_origins.borrow()[vid.index as usize].clone()
479 /// Creates a new skolemized region. Skolemized regions are fresh
480 /// regions used when performing higher-ranked computations. They
481 /// must be used in a very particular way and are never supposed
482 /// to "escape" out into error messages or the code at large.
484 /// The idea is to always create a snapshot. Skolemized regions
485 /// can be created in the context of this snapshot, but before the
486 /// snapshot is committed or rolled back, they must be popped
487 /// (using `pop_skolemized_regions`), so that their numbers can be
488 /// recycled. Normally you don't have to think about this: you use
489 /// the APIs in `higher_ranked/mod.rs`, such as
490 /// `skolemize_late_bound_regions` and `plug_leaks`, which will
491 /// guide you on this path (ensure that the `SkolemizationMap` is
492 /// consumed and you are good). There are also somewhat extensive
493 /// comments in `higher_ranked/README.md`.
495 /// The `snapshot` argument to this function is not really used;
496 /// it's just there to make it explicit which snapshot bounds the
497 /// skolemized region that results. It should always be the top-most snapshot.
498 pub fn push_skolemized(&self, br: ty::BoundRegion, snapshot: &RegionSnapshot)
500 assert!(self.in_snapshot());
501 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
503 let sc = self.skolemization_count.get();
504 self.skolemization_count.set(sc + 1);
505 self.tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
508 /// Removes all the edges to/from the skolemized regions that are
509 /// in `skols`. This is used after a higher-ranked operation
510 /// completes to remove all trace of the skolemized regions
511 /// created in that time.
512 pub fn pop_skolemized(&self,
513 skols: &FxHashSet<ty::Region<'tcx>>,
514 snapshot: &RegionSnapshot) {
515 debug!("pop_skolemized_regions(skols={:?})", skols);
517 assert!(self.in_snapshot());
518 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
519 assert!(self.skolemization_count.get() as usize >= skols.len(),
520 "popping more skolemized variables than actually exist, \
521 sc now = {}, skols.len = {}",
522 self.skolemization_count.get(),
525 let last_to_pop = self.skolemization_count.get();
526 let first_to_pop = last_to_pop - (skols.len() as u32);
528 assert!(first_to_pop >= snapshot.skolemization_count,
529 "popping more regions than snapshot contains, \
530 sc now = {}, sc then = {}, skols.len = {}",
531 self.skolemization_count.get(),
532 snapshot.skolemization_count,
537 ty::ReSkolemized(index, _) =>
538 index.index >= first_to_pop &&
539 index.index < last_to_pop,
543 "invalid skolemization keys or keys out of range ({}..{}): {:?}",
544 snapshot.skolemization_count,
545 self.skolemization_count.get(),
549 let mut undo_log = self.undo_log.borrow_mut();
551 let constraints_to_kill: Vec<usize> =
555 .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry))
556 .map(|(index, _)| index)
559 for index in constraints_to_kill {
560 let undo_entry = mem::replace(&mut undo_log[index], Purged);
561 self.rollback_undo_entry(undo_entry);
564 self.skolemization_count.set(snapshot.skolemization_count);
567 fn kill_constraint<'tcx>(skols: &FxHashSet<ty::Region<'tcx>>,
568 undo_entry: &UndoLogEntry<'tcx>)
571 &AddConstraint(ConstrainVarSubVar(..)) =>
573 &AddConstraint(ConstrainRegSubVar(a, _)) =>
575 &AddConstraint(ConstrainVarSubReg(_, b)) =>
577 &AddConstraint(ConstrainRegSubReg(a, b)) =>
578 skols.contains(&a) || skols.contains(&b),
583 &AddCombination(_, ref two_regions) =>
584 skols.contains(&two_regions.a) ||
585 skols.contains(&two_regions.b),
596 pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> Region<'tcx> {
597 // Creates a fresh bound variable for use in GLB computations.
598 // See discussion of GLB computation in the large comment at
599 // the top of this file for more details.
601 // This computation is potentially wrong in the face of
602 // rollover. It's conceivable, if unlikely, that one might
603 // wind up with accidental capture for nested functions in
604 // that case, if the outer function had bound regions created
605 // a very long time before and the inner function somehow
606 // wound up rolling over such that supposedly fresh
607 // identifiers were in fact shadowed. For now, we just assert
608 // that there is no rollover -- eventually we should try to be
609 // robust against this possibility, either by checking the set
610 // of bound identifiers that appear in a given expression and
611 // ensure that we generate one that is distinct, or by
612 // changing the representation of bound regions in a fn
615 let sc = self.bound_count.get();
616 self.bound_count.set(sc + 1);
618 if sc >= self.bound_count.get() {
619 bug!("rollover in RegionInference new_bound()");
622 self.tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
625 fn values_are_none(&self) -> bool {
626 self.values.borrow().is_none()
629 fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
630 // cannot add constraints once regions are resolved
631 assert!(self.values_are_none());
633 debug!("RegionVarBindings: add_constraint({:?})", constraint);
635 if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
636 if self.in_snapshot() {
637 self.undo_log.borrow_mut().push(AddConstraint(constraint));
642 fn add_verify(&self, verify: Verify<'tcx>) {
643 // cannot add verifys once regions are resolved
644 assert!(self.values_are_none());
646 debug!("RegionVarBindings: add_verify({:?})", verify);
648 // skip no-op cases known to be satisfied
650 VerifyBound::AllBounds(ref bs) if bs.len() == 0 => { return; }
654 let mut verifys = self.verifys.borrow_mut();
655 let index = verifys.len();
656 verifys.push(verify);
657 if self.in_snapshot() {
658 self.undo_log.borrow_mut().push(AddVerify(index));
662 pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
663 // cannot add givens once regions are resolved
664 assert!(self.values_are_none());
666 let mut givens = self.givens.borrow_mut();
667 if givens.insert((sub, sup)) {
668 debug!("add_given({:?} <= {:?})", sub, sup);
670 self.undo_log.borrow_mut().push(AddGiven(sub, sup));
674 pub fn make_eqregion(&self,
675 origin: SubregionOrigin<'tcx>,
679 // Eventually, it would be nice to add direct support for
681 self.make_subregion(origin.clone(), sub, sup);
682 self.make_subregion(origin, sup, sub);
684 if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
685 self.unification_table.borrow_mut().union(sub, sup);
690 pub fn make_subregion(&self,
691 origin: SubregionOrigin<'tcx>,
694 // cannot add constraints once regions are resolved
695 assert!(self.values_are_none());
697 debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
703 (&ReLateBound(..), _) |
704 (_, &ReLateBound(..)) => {
705 span_bug!(origin.span(),
706 "cannot relate bound region: {:?} <= {:?}",
711 // all regions are subregions of static, so we can ignore this
713 (&ReVar(sub_id), &ReVar(sup_id)) => {
714 self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
716 (_, &ReVar(sup_id)) => {
717 self.add_constraint(ConstrainRegSubVar(sub, sup_id), origin);
719 (&ReVar(sub_id), _) => {
720 self.add_constraint(ConstrainVarSubReg(sub_id, sup), origin);
723 self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
728 /// See `Verify::VerifyGenericBound`
729 pub fn verify_generic_bound(&self,
730 origin: SubregionOrigin<'tcx>,
731 kind: GenericKind<'tcx>,
733 bound: VerifyBound<'tcx>) {
734 self.add_verify(Verify {
742 pub fn lub_regions(&self,
743 origin: SubregionOrigin<'tcx>,
747 // cannot add constraints once regions are resolved
748 assert!(self.values_are_none());
750 debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b);
752 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
753 r // nothing lives longer than static
761 self.combine_vars(Lub, a, b, origin.clone(), |this, old_r, new_r| {
762 this.make_subregion(origin.clone(), old_r, new_r)
768 pub fn glb_regions(&self,
769 origin: SubregionOrigin<'tcx>,
773 // cannot add constraints once regions are resolved
774 assert!(self.values_are_none());
776 debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b);
778 (&ReStatic, r) | (r, &ReStatic) => {
779 r // static lives longer than everything else
787 self.combine_vars(Glb, a, b, origin.clone(), |this, old_r, new_r| {
788 this.make_subregion(origin.clone(), new_r, old_r)
794 pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
795 match *self.values.borrow() {
797 span_bug!((*self.var_origins.borrow())[rid.index as usize].span(),
798 "attempt to resolve region variable before values have \
801 Some(ref values) => {
802 let r = lookup(self.tcx, values, rid);
803 debug!("resolve_var({:?}) = {:?}", rid, r);
809 pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
810 let vid = self.unification_table.borrow_mut().find_value(rid).min_vid;
811 self.tcx.mk_region(ty::ReVar(vid))
814 fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap<'tcx>> {
821 pub fn combine_vars<F>(&self,
825 origin: SubregionOrigin<'tcx>,
828 where F: FnMut(&RegionVarBindings<'a, 'gcx, 'tcx>, Region<'tcx>, Region<'tcx>)
830 let vars = TwoRegions { a: a, b: b };
831 if let Some(&c) = self.combine_map(t).borrow().get(&vars) {
832 return self.tcx.mk_region(ReVar(c));
834 let c = self.new_region_var(MiscVariable(origin.span()));
835 self.combine_map(t).borrow_mut().insert(vars, c);
836 if self.in_snapshot() {
837 self.undo_log.borrow_mut().push(AddCombination(t, vars));
839 relate(self, a, self.tcx.mk_region(ReVar(c)));
840 relate(self, b, self.tcx.mk_region(ReVar(c)));
841 debug!("combine_vars() c={:?}", c);
842 self.tcx.mk_region(ReVar(c))
845 pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
846 self.undo_log.borrow()[mark.length..]
850 AddVar(vid) => Some(vid),
857 /// Computes all regions that have been related to `r0` since the
858 /// mark `mark` was made---`r0` itself will be the first
859 /// entry. The `directions` parameter controls what kind of
860 /// relations are considered. For example, one can say that only
861 /// "incoming" edges to `r0` are desired, in which case one will
862 /// get the set of regions `{r|r <= r0}`. This is used when
863 /// checking whether skolemized regions are being improperly
864 /// related to other regions.
865 pub fn tainted(&self,
866 mark: &RegionSnapshot,
868 directions: TaintDirections)
869 -> FxHashSet<ty::Region<'tcx>> {
870 debug!("tainted(mark={:?}, r0={:?}, directions={:?})",
871 mark, r0, directions);
873 // `result_set` acts as a worklist: we explore all outgoing
874 // edges and add any new regions we find to result_set. This
875 // is not a terribly efficient implementation.
876 let mut taint_set = TaintSet::new(directions, r0);
877 taint_set.fixed_point(self.tcx,
878 &self.undo_log.borrow()[mark.length..],
879 &self.verifys.borrow());
880 debug!("tainted: result={:?}", taint_set.regions);
881 return taint_set.into_set();
884 /// This function performs the actual region resolution. It must be
885 /// called after all constraints have been added. It performs a
886 /// fixed-point iteration to find region values which satisfy all
887 /// constraints, assuming such values can be found; if they cannot,
888 /// errors are reported.
889 pub fn resolve_regions(&self,
890 region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
891 -> Vec<RegionResolutionError<'tcx>> {
892 debug!("RegionVarBindings: resolve_regions()");
893 let mut errors = vec![];
894 let v = self.infer_variable_values(region_rels, &mut errors);
895 *self.values.borrow_mut() = Some(v);
899 fn lub_concrete_regions(&self,
900 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
905 (&ReLateBound(..), _) |
906 (_, &ReLateBound(..)) |
909 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
912 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
913 r // nothing lives longer than static
916 (&ReEmpty, r) | (r, &ReEmpty) => {
917 r // everything lives longer than empty
920 (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
921 span_bug!((*self.var_origins.borrow())[v_id.index as usize].span(),
922 "lub_concrete_regions invoked with non-concrete \
923 regions: {:?}, {:?}",
928 (&ReEarlyBound(_), &ReScope(s_id)) |
929 (&ReScope(s_id), &ReEarlyBound(_)) |
930 (&ReFree(_), &ReScope(s_id)) |
931 (&ReScope(s_id), &ReFree(_)) => {
932 // A "free" region can be interpreted as "some region
933 // at least as big as fr.scope". So, we can
934 // reasonably compare free regions and scopes:
935 let fr_scope = match (a, b) {
936 (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
937 region_rels.region_maps.early_free_extent(self.tcx, br)
939 (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
940 region_rels.region_maps.free_extent(self.tcx, fr)
944 let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
945 if r_id == fr_scope {
946 // if the free region's scope `fr.scope` is bigger than
947 // the scope region `s_id`, then the LUB is the free
950 (_, &ReScope(_)) => return a,
951 (&ReScope(_), _) => return b,
956 // otherwise, we don't know what the free region is,
957 // so we must conservatively say the LUB is static:
958 self.tcx.types.re_static
961 (&ReScope(a_id), &ReScope(b_id)) => {
962 // The region corresponding to an outer block is a
963 // subtype of the region corresponding to an inner
965 let lub = region_rels.region_maps.nearest_common_ancestor(a_id, b_id);
966 self.tcx.mk_region(ReScope(lub))
969 (&ReEarlyBound(_), &ReEarlyBound(_)) |
970 (&ReFree(_), &ReEarlyBound(_)) |
971 (&ReEarlyBound(_), &ReFree(_)) |
972 (&ReFree(_), &ReFree(_)) => {
973 region_rels.lub_free_regions(a, b)
976 // For these types, we cannot define any additional
978 (&ReSkolemized(..), _) |
979 (_, &ReSkolemized(..)) => {
983 self.tcx.types.re_static
990 // ______________________________________________________________________
992 #[derive(Copy, Clone, Debug)]
993 pub enum VarValue<'tcx> {
998 struct RegionAndOrigin<'tcx> {
999 region: Region<'tcx>,
1000 origin: SubregionOrigin<'tcx>,
1003 type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
1005 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
1006 fn infer_variable_values(&self,
1007 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1008 errors: &mut Vec<RegionResolutionError<'tcx>>)
1009 -> Vec<VarValue<'tcx>> {
1010 let mut var_data = self.construct_var_data();
1012 // Dorky hack to cause `dump_constraints` to only get called
1013 // if debug mode is enabled:
1014 debug!("----() End constraint listing (context={:?}) {:?}---",
1015 region_rels.context,
1016 self.dump_constraints(region_rels));
1017 graphviz::maybe_print_constraints_for(self, region_rels);
1019 let graph = self.construct_graph();
1020 self.expand_givens(&graph);
1021 self.expansion(region_rels, &mut var_data);
1022 self.collect_errors(region_rels, &mut var_data, errors);
1023 self.collect_var_errors(region_rels, &var_data, &graph, errors);
1027 fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
1028 (0..self.num_vars() as usize)
1029 .map(|_| Value(self.tcx.types.re_empty))
1033 fn dump_constraints(&self, free_regions: &RegionRelations<'a, 'gcx, 'tcx>) {
1034 debug!("----() Start constraint listing (context={:?}) ()----",
1035 free_regions.context);
1036 for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
1037 debug!("Constraint {} => {:?}", idx, constraint);
1041 fn expand_givens(&self, graph: &RegionGraph) {
1042 // Givens are a kind of horrible hack to account for
1043 // constraints like 'c <= '0 that are known to hold due to
1044 // closure signatures (see the comment above on the `givens`
1045 // field). They should go away. But until they do, the role
1046 // of this fn is to account for the transitive nature:
1052 let mut givens = self.givens.borrow_mut();
1053 let seeds: Vec<_> = givens.iter().cloned().collect();
1054 for (r, vid) in seeds {
1055 let seed_index = NodeIndex(vid.index as usize);
1056 for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
1057 let succ_index = succ_index.0 as u32;
1058 if succ_index < self.num_vars() {
1059 let succ_vid = RegionVid { index: succ_index };
1060 givens.insert((r, succ_vid));
1067 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1068 var_values: &mut [VarValue<'tcx>]) {
1069 self.iterate_until_fixed_point("Expansion", |constraint, origin| {
1070 debug!("expansion: constraint={:?} origin={:?}",
1071 constraint, origin);
1073 ConstrainRegSubVar(a_region, b_vid) => {
1074 let b_data = &mut var_values[b_vid.index as usize];
1075 self.expand_node(region_rels, a_region, b_vid, b_data)
1077 ConstrainVarSubVar(a_vid, b_vid) => {
1078 match var_values[a_vid.index as usize] {
1079 ErrorValue => false,
1080 Value(a_region) => {
1081 let b_node = &mut var_values[b_vid.index as usize];
1082 self.expand_node(region_rels, a_region, b_vid, b_node)
1086 ConstrainRegSubReg(..) |
1087 ConstrainVarSubReg(..) => {
1088 // These constraints are checked after expansion
1089 // is done, in `collect_errors`.
1096 fn expand_node(&self,
1097 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1098 a_region: Region<'tcx>,
1100 b_data: &mut VarValue<'tcx>)
1102 debug!("expand_node({:?}, {:?} == {:?})",
1107 // Check if this relationship is implied by a given.
1109 ty::ReEarlyBound(_) |
1111 if self.givens.borrow().contains(&(a_region, b_vid)) {
1120 Value(cur_region) => {
1121 let lub = self.lub_concrete_regions(region_rels, a_region, cur_region);
1122 if lub == cur_region {
1126 debug!("Expanding value of {:?} from {:?} to {:?}",
1131 *b_data = Value(lub);
1141 /// After expansion is complete, go and check upper bounds (i.e.,
1142 /// cases where the region cannot grow larger than a fixed point)
1143 /// and check that they are satisfied.
1144 fn collect_errors(&self,
1145 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1146 var_data: &mut Vec<VarValue<'tcx>>,
1147 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1148 let constraints = self.constraints.borrow();
1149 for (constraint, origin) in constraints.iter() {
1150 debug!("collect_errors: constraint={:?} origin={:?}",
1151 constraint, origin);
1153 ConstrainRegSubVar(..) |
1154 ConstrainVarSubVar(..) => {
1155 // Expansion will ensure that these constraints hold. Ignore.
1158 ConstrainRegSubReg(sub, sup) => {
1159 if region_rels.is_subregion_of(sub, sup) {
1163 debug!("collect_errors: region error at {:?}: \
1164 cannot verify that {:?} <= {:?}",
1169 errors.push(ConcreteFailure((*origin).clone(), sub, sup));
1172 ConstrainVarSubReg(a_vid, b_region) => {
1173 let a_data = &mut var_data[a_vid.index as usize];
1174 debug!("contraction: {:?} == {:?}, {:?}",
1179 let a_region = match *a_data {
1180 ErrorValue => continue,
1181 Value(a_region) => a_region,
1184 // Do not report these errors immediately:
1185 // instead, set the variable value to error and
1186 // collect them later.
1187 if !region_rels.is_subregion_of(a_region, b_region) {
1188 debug!("collect_errors: region error at {:?}: \
1189 cannot verify that {:?}={:?} <= {:?}",
1194 *a_data = ErrorValue;
1200 for verify in self.verifys.borrow().iter() {
1201 debug!("collect_errors: verify={:?}", verify);
1202 let sub = normalize(self.tcx, var_data, verify.region);
1203 if verify.bound.is_met(region_rels, var_data, sub) {
1207 debug!("collect_errors: region error at {:?}: \
1208 cannot verify that {:?} <= {:?}",
1213 errors.push(GenericBoundFailure(verify.origin.clone(),
1214 verify.kind.clone(),
1219 /// Go over the variables that were declared to be error variables
1220 /// and create a `RegionResolutionError` for each of them.
1221 fn collect_var_errors(&self,
1222 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1223 var_data: &[VarValue<'tcx>],
1224 graph: &RegionGraph<'tcx>,
1225 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1226 debug!("collect_var_errors");
1228 // This is the best way that I have found to suppress
1229 // duplicate and related errors. Basically we keep a set of
1230 // flags for every node. Whenever an error occurs, we will
1231 // walk some portion of the graph looking to find pairs of
1232 // conflicting regions to report to the user. As we walk, we
1233 // trip the flags from false to true, and if we find that
1234 // we've already reported an error involving any particular
1235 // node we just stop and don't report the current error. The
1236 // idea is to report errors that derive from independent
1237 // regions of the graph, but not those that derive from
1238 // overlapping locations.
1239 let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
1241 for idx in 0..self.num_vars() as usize {
1242 match var_data[idx] {
1244 /* Inference successful */
1247 /* Inference impossible, this value contains
1248 inconsistent constraints.
1250 I think that in this case we should report an
1251 error now---unlike the case above, we can't
1252 wait to see whether the user needs the result
1253 of this variable. The reason is that the mere
1254 existence of this variable implies that the
1255 region graph is inconsistent, whether or not it
1258 For example, we may have created a region
1259 variable that is the GLB of two other regions
1260 which do not have a GLB. Even if that variable
1261 is not used, it implies that those two regions
1262 *should* have a GLB.
1264 At least I think this is true. It may be that
1265 the mere existence of a conflict in a region variable
1266 that is not used is not a problem, so if this rule
1267 starts to create problems we'll have to revisit
1268 this portion of the code and think hard about it. =) */
1270 let node_vid = RegionVid { index: idx as u32 };
1271 self.collect_error_for_expanding_node(region_rels,
1281 fn construct_graph(&self) -> RegionGraph<'tcx> {
1282 let num_vars = self.num_vars();
1284 let constraints = self.constraints.borrow();
1286 let mut graph = graph::Graph::new();
1288 for _ in 0..num_vars {
1292 // Issue #30438: two distinct dummy nodes, one for incoming
1293 // edges (dummy_source) and another for outgoing edges
1294 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
1295 // dummy node leads one to think (erroneously) there exists a
1296 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
1297 let dummy_source = graph.add_node(());
1298 let dummy_sink = graph.add_node(());
1300 for (constraint, _) in constraints.iter() {
1302 ConstrainVarSubVar(a_id, b_id) => {
1303 graph.add_edge(NodeIndex(a_id.index as usize),
1304 NodeIndex(b_id.index as usize),
1307 ConstrainRegSubVar(_, b_id) => {
1308 graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
1310 ConstrainVarSubReg(a_id, _) => {
1311 graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
1313 ConstrainRegSubReg(..) => {
1314 // this would be an edge from `dummy_source` to
1315 // `dummy_sink`; just ignore it.
1323 fn collect_error_for_expanding_node(&self,
1324 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1325 graph: &RegionGraph<'tcx>,
1326 dup_vec: &mut [u32],
1327 node_idx: RegionVid,
1328 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1329 // Errors in expanding nodes result from a lower-bound that is
1330 // not contained by an upper-bound.
1331 let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph,
1335 let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph,
1340 if lower_dup || upper_dup {
1344 // We place free regions first because we are special casing
1345 // SubSupConflict(ReFree, ReFree) when reporting error, and so
1346 // the user will more likely get a specific suggestion.
1347 fn region_order_key(x: &RegionAndOrigin) -> u8 {
1349 ReEarlyBound(_) => 0,
1354 lower_bounds.sort_by_key(region_order_key);
1355 upper_bounds.sort_by_key(region_order_key);
1357 for lower_bound in &lower_bounds {
1358 for upper_bound in &upper_bounds {
1359 if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
1360 let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1361 debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
1366 upper_bound.region);
1367 errors.push(SubSupConflict(origin,
1368 lower_bound.origin.clone(),
1370 upper_bound.origin.clone(),
1371 upper_bound.region));
1377 span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
1378 "collect_error_for_expanding_node() could not find \
1379 error for var {:?}, lower_bounds={:?}, \
1386 fn collect_concrete_regions(&self,
1387 graph: &RegionGraph<'tcx>,
1388 orig_node_idx: RegionVid,
1390 dup_vec: &mut [u32])
1391 -> (Vec<RegionAndOrigin<'tcx>>, bool) {
1392 struct WalkState<'tcx> {
1393 set: FxHashSet<RegionVid>,
1394 stack: Vec<RegionVid>,
1395 result: Vec<RegionAndOrigin<'tcx>>,
1398 let mut state = WalkState {
1400 stack: vec![orig_node_idx],
1404 state.set.insert(orig_node_idx);
1406 // to start off the process, walk the source node in the
1407 // direction specified
1408 process_edges(self, &mut state, graph, orig_node_idx, dir);
1410 while !state.stack.is_empty() {
1411 let node_idx = state.stack.pop().unwrap();
1413 // check whether we've visited this node on some previous walk
1414 if dup_vec[node_idx.index as usize] == u32::MAX {
1415 dup_vec[node_idx.index as usize] = orig_node_idx.index;
1416 } else if dup_vec[node_idx.index as usize] != orig_node_idx.index {
1417 state.dup_found = true;
1420 debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
1424 process_edges(self, &mut state, graph, node_idx, dir);
1427 let WalkState {result, dup_found, ..} = state;
1428 return (result, dup_found);
1430 fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
1431 state: &mut WalkState<'tcx>,
1432 graph: &RegionGraph<'tcx>,
1433 source_vid: RegionVid,
1435 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
1437 let source_node_index = NodeIndex(source_vid.index as usize);
1438 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
1440 ConstrainVarSubVar(from_vid, to_vid) => {
1441 let opp_vid = if from_vid == source_vid {
1446 if state.set.insert(opp_vid) {
1447 state.stack.push(opp_vid);
1451 ConstrainRegSubVar(region, _) |
1452 ConstrainVarSubReg(_, region) => {
1453 state.result.push(RegionAndOrigin {
1455 origin: this.constraints.borrow().get(&edge.data).unwrap().clone(),
1459 ConstrainRegSubReg(..) => {
1460 panic!("cannot reach reg-sub-reg edge in region inference \
1468 fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
1469 where F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool
1471 let mut iteration = 0;
1472 let mut changed = true;
1476 debug!("---- {} Iteration {}{}", "#", tag, iteration);
1477 for (constraint, origin) in self.constraints.borrow().iter() {
1478 let edge_changed = body(constraint, origin);
1480 debug!("Updated due to constraint {:?}", constraint);
1485 debug!("---- {} Complete after {} iteration(s)", tag, iteration);
1490 fn normalize<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1491 values: &Vec<VarValue<'tcx>>,
1492 r: ty::Region<'tcx>)
1493 -> ty::Region<'tcx> {
1495 ty::ReVar(rid) => lookup(tcx, values, rid),
1500 fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1501 values: &Vec<VarValue<'tcx>>,
1503 -> ty::Region<'tcx> {
1504 match values[rid.index as usize] {
1506 ErrorValue => tcx.types.re_static, // Previously reported error.
1510 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
1511 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1512 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
1516 impl fmt::Debug for RegionSnapshot {
1517 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1518 write!(f, "RegionSnapshot(length={},skolemization={})",
1519 self.length, self.skolemization_count)
1523 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
1524 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1526 GenericKind::Param(ref p) => write!(f, "{:?}", p),
1527 GenericKind::Projection(ref p) => write!(f, "{:?}", p),
1532 impl<'tcx> fmt::Display for GenericKind<'tcx> {
1533 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1535 GenericKind::Param(ref p) => write!(f, "{}", p),
1536 GenericKind::Projection(ref p) => write!(f, "{}", p),
1541 impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
1542 pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1544 GenericKind::Param(ref p) => p.to_ty(tcx),
1545 GenericKind::Projection(ref p) => tcx.mk_projection(
1546 p.trait_ref.clone(), p.item_name(tcx)),
1551 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
1552 fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) {
1554 &VerifyBound::AnyRegion(ref rs) |
1555 &VerifyBound::AllRegions(ref rs) => for &r in rs {
1559 &VerifyBound::AnyBound(ref bs) |
1560 &VerifyBound::AllBounds(ref bs) => for b in bs {
1561 b.for_each_region(f);
1566 pub fn must_hold(&self) -> bool {
1568 &VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
1569 &VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1570 &VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1571 &VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1575 pub fn cannot_hold(&self) -> bool {
1577 &VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1578 &VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
1579 &VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1580 &VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1584 pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1585 if self.must_hold() || vb.cannot_hold() {
1587 } else if self.cannot_hold() || vb.must_hold() {
1590 VerifyBound::AnyBound(vec![self, vb])
1594 pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1595 if self.must_hold() && vb.must_hold() {
1597 } else if self.cannot_hold() && vb.cannot_hold() {
1600 VerifyBound::AllBounds(vec![self, vb])
1605 region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
1606 var_values: &Vec<VarValue<'tcx>>,
1607 min: ty::Region<'tcx>)
1609 let tcx = region_rels.tcx;
1611 &VerifyBound::AnyRegion(ref rs) =>
1613 .map(|&r| normalize(tcx, var_values, r))
1614 .any(|r| region_rels.is_subregion_of(min, r)),
1616 &VerifyBound::AllRegions(ref rs) =>
1618 .map(|&r| normalize(tcx, var_values, r))
1619 .all(|r| region_rels.is_subregion_of(min, r)),
1621 &VerifyBound::AnyBound(ref bs) =>
1623 .any(|b| b.is_met(region_rels, var_values, min)),
1625 &VerifyBound::AllBounds(ref bs) =>
1627 .all(|b| b.is_met(region_rels, var_values, min)),