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::FreeRegionMap;
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};
40 // A constraint that influences the inference process.
41 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
42 pub enum Constraint<'tcx> {
43 // One region variable is subregion of another
44 ConstrainVarSubVar(RegionVid, RegionVid),
46 // Concrete region is subregion of region variable
47 ConstrainRegSubVar(&'tcx Region, RegionVid),
49 // Region variable is subregion of concrete region. This does not
50 // directly affect inference, but instead is checked after
51 // inference is complete.
52 ConstrainVarSubReg(RegionVid, &'tcx Region),
54 // A constraint where neither side is a variable. This does not
55 // directly affect inference, but instead is checked after
56 // inference is complete.
57 ConstrainRegSubReg(&'tcx Region, &'tcx Region),
60 // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
61 // associated type) must outlive the region `R`. `T` is known to
62 // outlive `RS`. Therefore verify that `R <= RS[i]` for some
63 // `i`. Inference variables may be involved (but this verification
64 // step doesn't influence inference).
66 pub struct Verify<'tcx> {
67 kind: GenericKind<'tcx>,
68 origin: SubregionOrigin<'tcx>,
70 bound: VerifyBound<'tcx>,
73 #[derive(Copy, Clone, PartialEq, Eq)]
74 pub enum GenericKind<'tcx> {
76 Projection(ty::ProjectionTy<'tcx>),
79 // When we introduce a verification step, we wish to test that a
80 // particular region (let's call it `'min`) meets some bound.
81 // The bound is described the by the following grammar:
83 pub enum VerifyBound<'tcx> {
84 // B = exists {R} --> some 'r in {R} must outlive 'min
86 // Put another way, the subject value is known to outlive all
87 // regions in {R}, so if any of those outlives 'min, then the
89 AnyRegion(Vec<&'tcx Region>),
91 // B = forall {R} --> all 'r in {R} must outlive 'min
93 // Put another way, the subject value is known to outlive some
94 // region in {R}, so if all of those outlives 'min, then the bound
96 AllRegions(Vec<&'tcx Region>),
98 // B = exists {B} --> 'min must meet some bound b in {B}
99 AnyBound(Vec<VerifyBound<'tcx>>),
101 // B = forall {B} --> 'min must meet all bounds b in {B}
102 AllBounds(Vec<VerifyBound<'tcx>>),
105 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
106 pub struct TwoRegions<'tcx> {
111 #[derive(Copy, Clone, PartialEq)]
112 pub enum UndoLogEntry<'tcx> {
113 /// Pushed when we start a snapshot.
116 /// Replaces an `OpenSnapshot` when a snapshot is committed, but
117 /// that snapshot is not the root. If the root snapshot is
118 /// unrolled, all nested snapshots must be committed.
121 /// We added `RegionVid`
124 /// We added the given `constraint`
125 AddConstraint(Constraint<'tcx>),
127 /// We added the given `verify`
130 /// We added the given `given`
131 AddGiven(ty::FreeRegion, ty::RegionVid),
133 /// We added a GLB/LUB "combinaton variable"
134 AddCombination(CombineMapType, TwoRegions<'tcx>),
136 /// During skolemization, we sometimes purge entries from the undo
137 /// log in a kind of minisnapshot (unlike other snapshots, this
138 /// purging actually takes place *on success*). In that case, we
139 /// replace the corresponding entry with `Noop` so as to avoid the
140 /// need to do a bunch of swapping. (We can't use `swap_remove` as
141 /// the order of the vector is important.)
145 #[derive(Copy, Clone, PartialEq)]
146 pub enum CombineMapType {
151 #[derive(Clone, Debug)]
152 pub enum RegionResolutionError<'tcx> {
153 /// `ConcreteFailure(o, a, b)`:
155 /// `o` requires that `a <= b`, but this does not hold
156 ConcreteFailure(SubregionOrigin<'tcx>, &'tcx Region, &'tcx Region),
158 /// `GenericBoundFailure(p, s, a)
160 /// The parameter/associated-type `p` must be known to outlive the lifetime
161 /// `a` (but none of the known bounds are sufficient).
162 GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, &'tcx Region),
164 /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
166 /// Could not infer a value for `v` because `sub_r <= v` (due to
167 /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
168 /// `sub_r <= sup_r` does not hold.
169 SubSupConflict(RegionVariableOrigin,
170 SubregionOrigin<'tcx>,
172 SubregionOrigin<'tcx>,
176 #[derive(Clone, Debug)]
177 pub enum ProcessedErrorOrigin<'tcx> {
178 ConcreteFailure(SubregionOrigin<'tcx>, &'tcx Region, &'tcx Region),
179 VariableFailure(RegionVariableOrigin),
182 pub type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
184 pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
185 tcx: TyCtxt<'a, 'gcx, 'tcx>,
186 var_origins: RefCell<Vec<RegionVariableOrigin>>,
188 // Constraints of the form `A <= B` introduced by the region
189 // checker. Here at least one of `A` and `B` must be a region
191 constraints: RefCell<FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>>,
193 // A "verify" is something that we need to verify after inference is
194 // done, but which does not directly affect inference in any way.
196 // An example is a `A <= B` where neither `A` nor `B` are
197 // inference variables.
198 verifys: RefCell<Vec<Verify<'tcx>>>,
200 // A "given" is a relationship that is known to hold. In particular,
201 // we often know from closure fn signatures that a particular free
202 // region must be a subregion of a region variable:
204 // foo.iter().filter(<'a> |x: &'a &'b T| ...)
206 // In situations like this, `'b` is in fact a region variable
207 // introduced by the call to `iter()`, and `'a` is a bound region
208 // on the closure (as indicated by the `<'a>` prefix). If we are
209 // naive, we wind up inferring that `'b` must be `'static`,
210 // because we require that it be greater than `'a` and we do not
211 // know what `'a` is precisely.
213 // This hashmap is used to avoid that naive scenario. Basically we
214 // record the fact that `'a <= 'b` is implied by the fn signature,
215 // and then ignore the constraint when solving equations. This is
216 // a bit of a hack but seems to work.
217 givens: RefCell<FxHashSet<(ty::FreeRegion, ty::RegionVid)>>,
219 lubs: RefCell<CombineMap<'tcx>>,
220 glbs: RefCell<CombineMap<'tcx>>,
221 skolemization_count: Cell<u32>,
222 bound_count: Cell<u32>,
224 // The undo log records actions that might later be undone.
226 // Note: when the undo_log is empty, we are not actively
227 // snapshotting. When the `start_snapshot()` method is called, we
228 // push an OpenSnapshot entry onto the list to indicate that we
229 // are now actively snapshotting. The reason for this is that
230 // otherwise we end up adding entries for things like the lower
231 // bound on a variable and so forth, which can never be rolled
233 undo_log: RefCell<Vec<UndoLogEntry<'tcx>>>,
234 unification_table: RefCell<UnificationTable<ty::RegionVid>>,
236 // This contains the results of inference. It begins as an empty
237 // option and only acquires a value after inference is complete.
238 values: RefCell<Option<Vec<VarValue<'tcx>>>>,
241 pub struct RegionSnapshot {
243 region_snapshot: unify::Snapshot<ty::RegionVid>,
244 skolemization_count: u32,
247 /// When working with skolemized regions, we often wish to find all of
248 /// the regions that are either reachable from a skolemized region, or
249 /// which can reach a skolemized region, or both. We call such regions
250 /// *tained* regions. This struct allows you to decide what set of
251 /// tainted regions you want.
253 pub struct TaintDirections {
258 impl TaintDirections {
259 pub fn incoming() -> Self {
260 TaintDirections { incoming: true, outgoing: false }
263 pub fn outgoing() -> Self {
264 TaintDirections { incoming: false, outgoing: true }
267 pub fn both() -> Self {
268 TaintDirections { incoming: true, outgoing: true }
272 struct TaintSet<'tcx> {
273 directions: TaintDirections,
274 regions: FxHashSet<&'tcx ty::Region>
277 impl<'a, 'gcx, 'tcx> TaintSet<'tcx> {
278 fn new(directions: TaintDirections,
279 initial_region: &'tcx ty::Region)
281 let mut regions = FxHashSet();
282 regions.insert(initial_region);
283 TaintSet { directions: directions, regions: regions }
286 fn fixed_point(&mut self,
287 tcx: TyCtxt<'a, 'gcx, 'tcx>,
288 undo_log: &[UndoLogEntry<'tcx>],
289 verifys: &[Verify<'tcx>]) {
290 let mut prev_len = 0;
291 while prev_len < self.len() {
292 debug!("tainted: prev_len = {:?} new_len = {:?}",
293 prev_len, self.len());
295 prev_len = self.len();
297 for undo_entry in undo_log {
299 &AddConstraint(ConstrainVarSubVar(a, b)) => {
300 self.add_edge(tcx.mk_region(ReVar(a)),
301 tcx.mk_region(ReVar(b)));
303 &AddConstraint(ConstrainRegSubVar(a, b)) => {
304 self.add_edge(a, tcx.mk_region(ReVar(b)));
306 &AddConstraint(ConstrainVarSubReg(a, b)) => {
307 self.add_edge(tcx.mk_region(ReVar(a)), b);
309 &AddConstraint(ConstrainRegSubReg(a, b)) => {
313 self.add_edge(tcx.mk_region(ReFree(a)),
314 tcx.mk_region(ReVar(b)));
317 verifys[i].bound.for_each_region(&mut |b| {
318 self.add_edge(verifys[i].region, b);
322 &AddCombination(..) |
325 &CommitedSnapshot => {}
331 fn into_set(self) -> FxHashSet<&'tcx ty::Region> {
335 fn len(&self) -> usize {
339 fn add_edge(&mut self,
340 source: &'tcx ty::Region,
341 target: &'tcx ty::Region) {
342 if self.directions.incoming {
343 if self.regions.contains(&target) {
344 self.regions.insert(source);
348 if self.directions.outgoing {
349 if self.regions.contains(&source) {
350 self.regions.insert(target);
356 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
357 pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
360 var_origins: RefCell::new(Vec::new()),
361 values: RefCell::new(None),
362 constraints: RefCell::new(FxHashMap()),
363 verifys: RefCell::new(Vec::new()),
364 givens: RefCell::new(FxHashSet()),
365 lubs: RefCell::new(FxHashMap()),
366 glbs: RefCell::new(FxHashMap()),
367 skolemization_count: Cell::new(0),
368 bound_count: Cell::new(0),
369 undo_log: RefCell::new(Vec::new()),
370 unification_table: RefCell::new(UnificationTable::new()),
374 fn in_snapshot(&self) -> bool {
375 !self.undo_log.borrow().is_empty()
378 pub fn start_snapshot(&self) -> RegionSnapshot {
379 let length = self.undo_log.borrow().len();
380 debug!("RegionVarBindings: start_snapshot({})", length);
381 self.undo_log.borrow_mut().push(OpenSnapshot);
384 region_snapshot: self.unification_table.borrow_mut().snapshot(),
385 skolemization_count: self.skolemization_count.get(),
389 pub fn commit(&self, snapshot: RegionSnapshot) {
390 debug!("RegionVarBindings: commit({})", snapshot.length);
391 assert!(self.undo_log.borrow().len() > snapshot.length);
392 assert!((*self.undo_log.borrow())[snapshot.length] == OpenSnapshot);
393 assert!(self.skolemization_count.get() == snapshot.skolemization_count,
394 "failed to pop skolemized regions: {} now vs {} at start",
395 self.skolemization_count.get(),
396 snapshot.skolemization_count);
398 let mut undo_log = self.undo_log.borrow_mut();
399 if snapshot.length == 0 {
400 undo_log.truncate(0);
402 (*undo_log)[snapshot.length] = CommitedSnapshot;
404 self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
407 pub fn rollback_to(&self, snapshot: RegionSnapshot) {
408 debug!("RegionVarBindings: rollback_to({:?})", snapshot);
409 let mut undo_log = self.undo_log.borrow_mut();
410 assert!(undo_log.len() > snapshot.length);
411 assert!((*undo_log)[snapshot.length] == OpenSnapshot);
412 while undo_log.len() > snapshot.length + 1 {
413 self.rollback_undo_entry(undo_log.pop().unwrap());
415 let c = undo_log.pop().unwrap();
416 assert!(c == OpenSnapshot);
417 self.skolemization_count.set(snapshot.skolemization_count);
418 self.unification_table.borrow_mut()
419 .rollback_to(snapshot.region_snapshot);
422 pub fn rollback_undo_entry(&self, undo_entry: UndoLogEntry<'tcx>) {
425 panic!("Failure to observe stack discipline");
427 Purged | CommitedSnapshot => {
428 // nothing to do here
431 let mut var_origins = self.var_origins.borrow_mut();
432 var_origins.pop().unwrap();
433 assert_eq!(var_origins.len(), vid.index as usize);
435 AddConstraint(ref constraint) => {
436 self.constraints.borrow_mut().remove(constraint);
438 AddVerify(index) => {
439 self.verifys.borrow_mut().pop();
440 assert_eq!(self.verifys.borrow().len(), index);
442 AddGiven(sub, sup) => {
443 self.givens.borrow_mut().remove(&(sub, sup));
445 AddCombination(Glb, ref regions) => {
446 self.glbs.borrow_mut().remove(regions);
448 AddCombination(Lub, ref regions) => {
449 self.lubs.borrow_mut().remove(regions);
454 pub fn num_vars(&self) -> u32 {
455 let len = self.var_origins.borrow().len();
456 // enforce no overflow
457 assert!(len as u32 as usize == len);
461 pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
462 let vid = RegionVid { index: self.num_vars() };
463 self.var_origins.borrow_mut().push(origin.clone());
465 let u_vid = self.unification_table.borrow_mut().new_key(
466 unify_key::RegionVidKey { min_vid: vid }
468 assert_eq!(vid, u_vid);
469 if self.in_snapshot() {
470 self.undo_log.borrow_mut().push(AddVar(vid));
472 debug!("created new region variable {:?} with origin {:?}",
478 pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
479 self.var_origins.borrow()[vid.index as usize].clone()
482 /// Creates a new skolemized region. Skolemized regions are fresh
483 /// regions used when performing higher-ranked computations. They
484 /// must be used in a very particular way and are never supposed
485 /// to "escape" out into error messages or the code at large.
487 /// The idea is to always create a snapshot. Skolemized regions
488 /// can be created in the context of this snapshot, but before the
489 /// snapshot is committed or rolled back, they must be popped
490 /// (using `pop_skolemized_regions`), so that their numbers can be
491 /// recycled. Normally you don't have to think about this: you use
492 /// the APIs in `higher_ranked/mod.rs`, such as
493 /// `skolemize_late_bound_regions` and `plug_leaks`, which will
494 /// guide you on this path (ensure that the `SkolemizationMap` is
495 /// consumed and you are good). There are also somewhat extensive
496 /// comments in `higher_ranked/README.md`.
498 /// The `snapshot` argument to this function is not really used;
499 /// it's just there to make it explicit which snapshot bounds the
500 /// skolemized region that results. It should always be the top-most snapshot.
501 pub fn push_skolemized(&self, br: ty::BoundRegion, snapshot: &RegionSnapshot)
503 assert!(self.in_snapshot());
504 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
506 let sc = self.skolemization_count.get();
507 self.skolemization_count.set(sc + 1);
508 self.tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
511 /// Removes all the edges to/from the skolemized regions that are
512 /// in `skols`. This is used after a higher-ranked operation
513 /// completes to remove all trace of the skolemized regions
514 /// created in that time.
515 pub fn pop_skolemized(&self,
516 skols: &FxHashSet<&'tcx ty::Region>,
517 snapshot: &RegionSnapshot) {
518 debug!("pop_skolemized_regions(skols={:?})", skols);
520 assert!(self.in_snapshot());
521 assert!(self.undo_log.borrow()[snapshot.length] == OpenSnapshot);
522 assert!(self.skolemization_count.get() as usize >= skols.len(),
523 "popping more skolemized variables than actually exist, \
524 sc now = {}, skols.len = {}",
525 self.skolemization_count.get(),
528 let last_to_pop = self.skolemization_count.get();
529 let first_to_pop = last_to_pop - (skols.len() as u32);
531 assert!(first_to_pop >= snapshot.skolemization_count,
532 "popping more regions than snapshot contains, \
533 sc now = {}, sc then = {}, skols.len = {}",
534 self.skolemization_count.get(),
535 snapshot.skolemization_count,
540 ty::ReSkolemized(index, _) =>
541 index.index >= first_to_pop &&
542 index.index < last_to_pop,
546 "invalid skolemization keys or keys out of range ({}..{}): {:?}",
547 snapshot.skolemization_count,
548 self.skolemization_count.get(),
552 let mut undo_log = self.undo_log.borrow_mut();
554 let constraints_to_kill: Vec<usize> =
558 .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry))
559 .map(|(index, _)| index)
562 for index in constraints_to_kill {
563 let undo_entry = mem::replace(&mut undo_log[index], Purged);
564 self.rollback_undo_entry(undo_entry);
567 self.skolemization_count.set(snapshot.skolemization_count);
570 fn kill_constraint<'tcx>(skols: &FxHashSet<&'tcx ty::Region>,
571 undo_entry: &UndoLogEntry<'tcx>)
574 &AddConstraint(ConstrainVarSubVar(..)) =>
576 &AddConstraint(ConstrainRegSubVar(a, _)) =>
578 &AddConstraint(ConstrainVarSubReg(_, b)) =>
580 &AddConstraint(ConstrainRegSubReg(a, b)) =>
581 skols.contains(&a) || skols.contains(&b),
586 &AddCombination(_, ref two_regions) =>
587 skols.contains(&two_regions.a) ||
588 skols.contains(&two_regions.b),
599 pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> &'tcx Region {
600 // Creates a fresh bound variable for use in GLB computations.
601 // See discussion of GLB computation in the large comment at
602 // the top of this file for more details.
604 // This computation is potentially wrong in the face of
605 // rollover. It's conceivable, if unlikely, that one might
606 // wind up with accidental capture for nested functions in
607 // that case, if the outer function had bound regions created
608 // a very long time before and the inner function somehow
609 // wound up rolling over such that supposedly fresh
610 // identifiers were in fact shadowed. For now, we just assert
611 // that there is no rollover -- eventually we should try to be
612 // robust against this possibility, either by checking the set
613 // of bound identifiers that appear in a given expression and
614 // ensure that we generate one that is distinct, or by
615 // changing the representation of bound regions in a fn
618 let sc = self.bound_count.get();
619 self.bound_count.set(sc + 1);
621 if sc >= self.bound_count.get() {
622 bug!("rollover in RegionInference new_bound()");
625 self.tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
628 fn values_are_none(&self) -> bool {
629 self.values.borrow().is_none()
632 fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
633 // cannot add constraints once regions are resolved
634 assert!(self.values_are_none());
636 debug!("RegionVarBindings: add_constraint({:?})", constraint);
638 if self.constraints.borrow_mut().insert(constraint, origin).is_none() {
639 if self.in_snapshot() {
640 self.undo_log.borrow_mut().push(AddConstraint(constraint));
645 fn add_verify(&self, verify: Verify<'tcx>) {
646 // cannot add verifys once regions are resolved
647 assert!(self.values_are_none());
649 debug!("RegionVarBindings: add_verify({:?})", verify);
651 // skip no-op cases known to be satisfied
653 VerifyBound::AllBounds(ref bs) if bs.len() == 0 => { return; }
657 let mut verifys = self.verifys.borrow_mut();
658 let index = verifys.len();
659 verifys.push(verify);
660 if self.in_snapshot() {
661 self.undo_log.borrow_mut().push(AddVerify(index));
665 pub fn add_given(&self, sub: ty::FreeRegion, sup: ty::RegionVid) {
666 // cannot add givens once regions are resolved
667 assert!(self.values_are_none());
669 let mut givens = self.givens.borrow_mut();
670 if givens.insert((sub, sup)) {
671 debug!("add_given({:?} <= {:?})", sub, sup);
673 self.undo_log.borrow_mut().push(AddGiven(sub, sup));
677 pub fn make_eqregion(&self,
678 origin: SubregionOrigin<'tcx>,
682 // Eventually, it would be nice to add direct support for
684 self.make_subregion(origin.clone(), sub, sup);
685 self.make_subregion(origin, sup, sub);
687 if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
688 self.unification_table.borrow_mut().union(sub, sup);
693 pub fn make_subregion(&self,
694 origin: SubregionOrigin<'tcx>,
697 // cannot add constraints once regions are resolved
698 assert!(self.values_are_none());
700 debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
706 (&ReEarlyBound(..), _) |
707 (&ReLateBound(..), _) |
708 (_, &ReEarlyBound(..)) |
709 (_, &ReLateBound(..)) => {
710 span_bug!(origin.span(),
711 "cannot relate bound region: {:?} <= {:?}",
716 // all regions are subregions of static, so we can ignore this
718 (&ReVar(sub_id), &ReVar(sup_id)) => {
719 self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
721 (_, &ReVar(sup_id)) => {
722 self.add_constraint(ConstrainRegSubVar(sub, sup_id), origin);
724 (&ReVar(sub_id), _) => {
725 self.add_constraint(ConstrainVarSubReg(sub_id, sup), origin);
728 self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
733 /// See `Verify::VerifyGenericBound`
734 pub fn verify_generic_bound(&self,
735 origin: SubregionOrigin<'tcx>,
736 kind: GenericKind<'tcx>,
738 bound: VerifyBound<'tcx>) {
739 self.add_verify(Verify {
747 pub fn lub_regions(&self,
748 origin: SubregionOrigin<'tcx>,
752 // cannot add constraints once regions are resolved
753 assert!(self.values_are_none());
755 debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b);
757 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
758 r // nothing lives longer than static
766 self.combine_vars(Lub, a, b, origin.clone(), |this, old_r, new_r| {
767 this.make_subregion(origin.clone(), old_r, new_r)
773 pub fn glb_regions(&self,
774 origin: SubregionOrigin<'tcx>,
778 // cannot add constraints once regions are resolved
779 assert!(self.values_are_none());
781 debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b);
783 (&ReStatic, r) | (r, &ReStatic) => {
784 r // static lives longer than everything else
792 self.combine_vars(Glb, a, b, origin.clone(), |this, old_r, new_r| {
793 this.make_subregion(origin.clone(), new_r, old_r)
799 pub fn resolve_var(&self, rid: RegionVid) -> &'tcx ty::Region {
800 match *self.values.borrow() {
802 span_bug!((*self.var_origins.borrow())[rid.index as usize].span(),
803 "attempt to resolve region variable before values have \
806 Some(ref values) => {
807 let r = lookup(self.tcx, values, rid);
808 debug!("resolve_var({:?}) = {:?}", rid, r);
814 pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> &'tcx ty::Region {
815 let vid = self.unification_table.borrow_mut().find_value(rid).min_vid;
816 self.tcx.mk_region(ty::ReVar(vid))
819 fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap<'tcx>> {
826 pub fn combine_vars<F>(&self,
830 origin: SubregionOrigin<'tcx>,
833 where F: FnMut(&RegionVarBindings<'a, 'gcx, 'tcx>, &'tcx Region, &'tcx Region)
835 let vars = TwoRegions { a: a, b: b };
836 if let Some(&c) = self.combine_map(t).borrow().get(&vars) {
837 return self.tcx.mk_region(ReVar(c));
839 let c = self.new_region_var(MiscVariable(origin.span()));
840 self.combine_map(t).borrow_mut().insert(vars, c);
841 if self.in_snapshot() {
842 self.undo_log.borrow_mut().push(AddCombination(t, vars));
844 relate(self, a, self.tcx.mk_region(ReVar(c)));
845 relate(self, b, self.tcx.mk_region(ReVar(c)));
846 debug!("combine_vars() c={:?}", c);
847 self.tcx.mk_region(ReVar(c))
850 pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
851 self.undo_log.borrow()[mark.length..]
855 AddVar(vid) => Some(vid),
862 /// Computes all regions that have been related to `r0` since the
863 /// mark `mark` was made---`r0` itself will be the first
864 /// entry. The `directions` parameter controls what kind of
865 /// relations are considered. For example, one can say that only
866 /// "incoming" edges to `r0` are desired, in which case one will
867 /// get the set of regions `{r|r <= r0}`. This is used when
868 /// checking whether skolemized regions are being improperly
869 /// related to other regions.
870 pub fn tainted(&self,
871 mark: &RegionSnapshot,
873 directions: TaintDirections)
874 -> FxHashSet<&'tcx ty::Region> {
875 debug!("tainted(mark={:?}, r0={:?}, directions={:?})",
876 mark, r0, directions);
878 // `result_set` acts as a worklist: we explore all outgoing
879 // edges and add any new regions we find to result_set. This
880 // is not a terribly efficient implementation.
881 let mut taint_set = TaintSet::new(directions, r0);
882 taint_set.fixed_point(self.tcx,
883 &self.undo_log.borrow()[mark.length..],
884 &self.verifys.borrow());
885 debug!("tainted: result={:?}", taint_set.regions);
886 return taint_set.into_set();
889 /// This function performs the actual region resolution. It must be
890 /// called after all constraints have been added. It performs a
891 /// fixed-point iteration to find region values which satisfy all
892 /// constraints, assuming such values can be found; if they cannot,
893 /// errors are reported.
894 pub fn resolve_regions(&self,
895 free_regions: &FreeRegionMap,
896 subject_node: ast::NodeId)
897 -> Vec<RegionResolutionError<'tcx>> {
898 debug!("RegionVarBindings: resolve_regions()");
899 let mut errors = vec![];
900 let v = self.infer_variable_values(free_regions, &mut errors, subject_node);
901 *self.values.borrow_mut() = Some(v);
905 fn lub_concrete_regions(&self,
906 free_regions: &FreeRegionMap,
911 (&ReLateBound(..), _) |
912 (_, &ReLateBound(..)) |
913 (&ReEarlyBound(..), _) |
914 (_, &ReEarlyBound(..)) |
917 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
920 (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
921 r // nothing lives longer than static
924 (&ReEmpty, r) | (r, &ReEmpty) => {
925 r // everything lives longer than empty
928 (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
929 span_bug!((*self.var_origins.borrow())[v_id.index as usize].span(),
930 "lub_concrete_regions invoked with non-concrete \
931 regions: {:?}, {:?}",
936 (&ReFree(fr), &ReScope(s_id)) |
937 (&ReScope(s_id), &ReFree(fr)) => {
938 // A "free" region can be interpreted as "some region
939 // at least as big as the block fr.scope_id". So, we can
940 // reasonably compare free regions and scopes:
941 let r_id = self.tcx.region_maps.nearest_common_ancestor(fr.scope, s_id);
943 if r_id == fr.scope {
944 // if the free region's scope `fr.scope_id` is bigger than
945 // the scope region `s_id`, then the LUB is the free
947 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.mk_region(ReStatic)
955 (&ReScope(a_id), &ReScope(b_id)) => {
956 // The region corresponding to an outer block is a
957 // subtype of the region corresponding to an inner
959 self.tcx.mk_region(ReScope(
960 self.tcx.region_maps.nearest_common_ancestor(a_id, b_id)))
963 (&ReFree(a_fr), &ReFree(b_fr)) => {
964 self.tcx.mk_region(free_regions.lub_free_regions(a_fr, b_fr))
967 // For these types, we cannot define any additional
969 (&ReSkolemized(..), _) |
970 (_, &ReSkolemized(..)) => {
974 self.tcx.mk_region(ReStatic)
981 // ______________________________________________________________________
983 #[derive(Copy, Clone, Debug)]
984 pub enum VarValue<'tcx> {
989 struct RegionAndOrigin<'tcx> {
990 region: &'tcx Region,
991 origin: SubregionOrigin<'tcx>,
994 type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
996 impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
997 fn infer_variable_values(&self,
998 free_regions: &FreeRegionMap,
999 errors: &mut Vec<RegionResolutionError<'tcx>>,
1000 subject: ast::NodeId)
1001 -> Vec<VarValue<'tcx>> {
1002 let mut var_data = self.construct_var_data();
1004 // Dorky hack to cause `dump_constraints` to only get called
1005 // if debug mode is enabled:
1006 debug!("----() End constraint listing (subject={}) {:?}---",
1008 self.dump_constraints(subject));
1009 graphviz::maybe_print_constraints_for(self, subject);
1011 let graph = self.construct_graph();
1012 self.expand_givens(&graph);
1013 self.expansion(free_regions, &mut var_data);
1014 self.collect_errors(free_regions, &mut var_data, errors);
1015 self.collect_var_errors(free_regions, &var_data, &graph, errors);
1019 fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
1020 (0..self.num_vars() as usize)
1021 .map(|_| Value(self.tcx.mk_region(ty::ReEmpty)))
1025 fn dump_constraints(&self, subject: ast::NodeId) {
1026 debug!("----() Start constraint listing (subject={}) ()----",
1028 for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
1029 debug!("Constraint {} => {:?}", idx, constraint);
1033 fn expand_givens(&self, graph: &RegionGraph) {
1034 // Givens are a kind of horrible hack to account for
1035 // constraints like 'c <= '0 that are known to hold due to
1036 // closure signatures (see the comment above on the `givens`
1037 // field). They should go away. But until they do, the role
1038 // of this fn is to account for the transitive nature:
1044 let mut givens = self.givens.borrow_mut();
1045 let seeds: Vec<_> = givens.iter().cloned().collect();
1046 for (fr, vid) in seeds {
1047 let seed_index = NodeIndex(vid.index as usize);
1048 for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
1049 let succ_index = succ_index.0 as u32;
1050 if succ_index < self.num_vars() {
1051 let succ_vid = RegionVid { index: succ_index };
1052 givens.insert((fr, succ_vid));
1058 fn expansion(&self, free_regions: &FreeRegionMap, var_values: &mut [VarValue<'tcx>]) {
1059 self.iterate_until_fixed_point("Expansion", |constraint, origin| {
1060 debug!("expansion: constraint={:?} origin={:?}",
1061 constraint, origin);
1063 ConstrainRegSubVar(a_region, b_vid) => {
1064 let b_data = &mut var_values[b_vid.index as usize];
1065 self.expand_node(free_regions, a_region, b_vid, b_data)
1067 ConstrainVarSubVar(a_vid, b_vid) => {
1068 match var_values[a_vid.index as usize] {
1069 ErrorValue => false,
1070 Value(a_region) => {
1071 let b_node = &mut var_values[b_vid.index as usize];
1072 self.expand_node(free_regions, a_region, b_vid, b_node)
1076 ConstrainRegSubReg(..) |
1077 ConstrainVarSubReg(..) => {
1078 // These constraints are checked after expansion
1079 // is done, in `collect_errors`.
1086 fn expand_node(&self,
1087 free_regions: &FreeRegionMap,
1088 a_region: &'tcx Region,
1090 b_data: &mut VarValue<'tcx>)
1092 debug!("expand_node({:?}, {:?} == {:?})",
1097 // Check if this relationship is implied by a given.
1100 if self.givens.borrow().contains(&(fr, b_vid)) {
1109 Value(cur_region) => {
1110 let lub = self.lub_concrete_regions(free_regions, a_region, cur_region);
1111 if lub == cur_region {
1115 debug!("Expanding value of {:?} from {:?} to {:?}",
1120 *b_data = Value(lub);
1130 /// After expansion is complete, go and check upper bounds (i.e.,
1131 /// cases where the region cannot grow larger than a fixed point)
1132 /// and check that they are satisfied.
1133 fn collect_errors(&self,
1134 free_regions: &FreeRegionMap,
1135 var_data: &mut Vec<VarValue<'tcx>>,
1136 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1137 let constraints = self.constraints.borrow();
1138 for (constraint, origin) in constraints.iter() {
1139 debug!("collect_errors: constraint={:?} origin={:?}",
1140 constraint, origin);
1142 ConstrainRegSubVar(..) |
1143 ConstrainVarSubVar(..) => {
1144 // Expansion will ensure that these constraints hold. Ignore.
1147 ConstrainRegSubReg(sub, sup) => {
1148 if free_regions.is_subregion_of(self.tcx, sub, sup) {
1152 debug!("collect_errors: region error at {:?}: \
1153 cannot verify that {:?} <= {:?}",
1158 errors.push(ConcreteFailure((*origin).clone(), sub, sup));
1161 ConstrainVarSubReg(a_vid, b_region) => {
1162 let a_data = &mut var_data[a_vid.index as usize];
1163 debug!("contraction: {:?} == {:?}, {:?}",
1168 let a_region = match *a_data {
1169 ErrorValue => continue,
1170 Value(a_region) => a_region,
1173 // Do not report these errors immediately:
1174 // instead, set the variable value to error and
1175 // collect them later.
1176 if !free_regions.is_subregion_of(self.tcx, a_region, b_region) {
1177 debug!("collect_errors: region error at {:?}: \
1178 cannot verify that {:?}={:?} <= {:?}",
1183 *a_data = ErrorValue;
1189 for verify in self.verifys.borrow().iter() {
1190 debug!("collect_errors: verify={:?}", verify);
1191 let sub = normalize(self.tcx, var_data, verify.region);
1192 if verify.bound.is_met(self.tcx, free_regions, var_data, sub) {
1196 debug!("collect_errors: region error at {:?}: \
1197 cannot verify that {:?} <= {:?}",
1202 errors.push(GenericBoundFailure(verify.origin.clone(),
1203 verify.kind.clone(),
1208 /// Go over the variables that were declared to be error variables
1209 /// and create a `RegionResolutionError` for each of them.
1210 fn collect_var_errors(&self,
1211 free_regions: &FreeRegionMap,
1212 var_data: &[VarValue<'tcx>],
1213 graph: &RegionGraph<'tcx>,
1214 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1215 debug!("collect_var_errors");
1217 // This is the best way that I have found to suppress
1218 // duplicate and related errors. Basically we keep a set of
1219 // flags for every node. Whenever an error occurs, we will
1220 // walk some portion of the graph looking to find pairs of
1221 // conflicting regions to report to the user. As we walk, we
1222 // trip the flags from false to true, and if we find that
1223 // we've already reported an error involving any particular
1224 // node we just stop and don't report the current error. The
1225 // idea is to report errors that derive from independent
1226 // regions of the graph, but not those that derive from
1227 // overlapping locations.
1228 let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
1230 for idx in 0..self.num_vars() as usize {
1231 match var_data[idx] {
1233 /* Inference successful */
1236 /* Inference impossible, this value contains
1237 inconsistent constraints.
1239 I think that in this case we should report an
1240 error now---unlike the case above, we can't
1241 wait to see whether the user needs the result
1242 of this variable. The reason is that the mere
1243 existence of this variable implies that the
1244 region graph is inconsistent, whether or not it
1247 For example, we may have created a region
1248 variable that is the GLB of two other regions
1249 which do not have a GLB. Even if that variable
1250 is not used, it implies that those two regions
1251 *should* have a GLB.
1253 At least I think this is true. It may be that
1254 the mere existence of a conflict in a region variable
1255 that is not used is not a problem, so if this rule
1256 starts to create problems we'll have to revisit
1257 this portion of the code and think hard about it. =) */
1259 let node_vid = RegionVid { index: idx as u32 };
1260 self.collect_error_for_expanding_node(free_regions,
1270 fn construct_graph(&self) -> RegionGraph<'tcx> {
1271 let num_vars = self.num_vars();
1273 let constraints = self.constraints.borrow();
1275 let mut graph = graph::Graph::new();
1277 for _ in 0..num_vars {
1281 // Issue #30438: two distinct dummy nodes, one for incoming
1282 // edges (dummy_source) and another for outgoing edges
1283 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
1284 // dummy node leads one to think (erroneously) there exists a
1285 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
1286 let dummy_source = graph.add_node(());
1287 let dummy_sink = graph.add_node(());
1289 for (constraint, _) in constraints.iter() {
1291 ConstrainVarSubVar(a_id, b_id) => {
1292 graph.add_edge(NodeIndex(a_id.index as usize),
1293 NodeIndex(b_id.index as usize),
1296 ConstrainRegSubVar(_, b_id) => {
1297 graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
1299 ConstrainVarSubReg(a_id, _) => {
1300 graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
1302 ConstrainRegSubReg(..) => {
1303 // this would be an edge from `dummy_source` to
1304 // `dummy_sink`; just ignore it.
1312 fn collect_error_for_expanding_node(&self,
1313 free_regions: &FreeRegionMap,
1314 graph: &RegionGraph<'tcx>,
1315 dup_vec: &mut [u32],
1316 node_idx: RegionVid,
1317 errors: &mut Vec<RegionResolutionError<'tcx>>) {
1318 // Errors in expanding nodes result from a lower-bound that is
1319 // not contained by an upper-bound.
1320 let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph,
1324 let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph,
1329 if lower_dup || upper_dup {
1333 // We place free regions first because we are special casing
1334 // SubSupConflict(ReFree, ReFree) when reporting error, and so
1335 // the user will more likely get a specific suggestion.
1336 fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
1337 match (a.region, b.region) {
1338 (&ReFree(..), &ReFree(..)) => Equal,
1339 (&ReFree(..), _) => Less,
1340 (_, &ReFree(..)) => Greater,
1344 lower_bounds.sort_by(|a, b| free_regions_first(a, b));
1345 upper_bounds.sort_by(|a, b| free_regions_first(a, b));
1347 for lower_bound in &lower_bounds {
1348 for upper_bound in &upper_bounds {
1349 if !free_regions.is_subregion_of(self.tcx, lower_bound.region, upper_bound.region) {
1350 let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1351 debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
1356 upper_bound.region);
1357 errors.push(SubSupConflict(origin,
1358 lower_bound.origin.clone(),
1360 upper_bound.origin.clone(),
1361 upper_bound.region));
1367 span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
1368 "collect_error_for_expanding_node() could not find \
1369 error for var {:?}, lower_bounds={:?}, \
1376 fn collect_concrete_regions(&self,
1377 graph: &RegionGraph<'tcx>,
1378 orig_node_idx: RegionVid,
1380 dup_vec: &mut [u32])
1381 -> (Vec<RegionAndOrigin<'tcx>>, bool) {
1382 struct WalkState<'tcx> {
1383 set: FxHashSet<RegionVid>,
1384 stack: Vec<RegionVid>,
1385 result: Vec<RegionAndOrigin<'tcx>>,
1388 let mut state = WalkState {
1390 stack: vec![orig_node_idx],
1394 state.set.insert(orig_node_idx);
1396 // to start off the process, walk the source node in the
1397 // direction specified
1398 process_edges(self, &mut state, graph, orig_node_idx, dir);
1400 while !state.stack.is_empty() {
1401 let node_idx = state.stack.pop().unwrap();
1403 // check whether we've visited this node on some previous walk
1404 if dup_vec[node_idx.index as usize] == u32::MAX {
1405 dup_vec[node_idx.index as usize] = orig_node_idx.index;
1406 } else if dup_vec[node_idx.index as usize] != orig_node_idx.index {
1407 state.dup_found = true;
1410 debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
1414 process_edges(self, &mut state, graph, node_idx, dir);
1417 let WalkState {result, dup_found, ..} = state;
1418 return (result, dup_found);
1420 fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
1421 state: &mut WalkState<'tcx>,
1422 graph: &RegionGraph<'tcx>,
1423 source_vid: RegionVid,
1425 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
1427 let source_node_index = NodeIndex(source_vid.index as usize);
1428 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
1430 ConstrainVarSubVar(from_vid, to_vid) => {
1431 let opp_vid = if from_vid == source_vid {
1436 if state.set.insert(opp_vid) {
1437 state.stack.push(opp_vid);
1441 ConstrainRegSubVar(region, _) |
1442 ConstrainVarSubReg(_, region) => {
1443 state.result.push(RegionAndOrigin {
1445 origin: this.constraints.borrow().get(&edge.data).unwrap().clone(),
1449 ConstrainRegSubReg(..) => {
1450 panic!("cannot reach reg-sub-reg edge in region inference \
1458 fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
1459 where F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool
1461 let mut iteration = 0;
1462 let mut changed = true;
1466 debug!("---- {} Iteration {}{}", "#", tag, iteration);
1467 for (constraint, origin) in self.constraints.borrow().iter() {
1468 let edge_changed = body(constraint, origin);
1470 debug!("Updated due to constraint {:?}", constraint);
1475 debug!("---- {} Complete after {} iteration(s)", tag, iteration);
1480 fn normalize<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1481 values: &Vec<VarValue<'tcx>>,
1482 r: &'tcx ty::Region)
1483 -> &'tcx ty::Region {
1485 ty::ReVar(rid) => lookup(tcx, values, rid),
1490 fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1491 values: &Vec<VarValue<'tcx>>,
1493 -> &'tcx ty::Region {
1494 match values[rid.index as usize] {
1496 ErrorValue => tcx.mk_region(ReStatic), // Previously reported error.
1500 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
1501 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1502 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
1506 impl fmt::Debug for RegionSnapshot {
1507 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1508 write!(f, "RegionSnapshot(length={},skolemization={})",
1509 self.length, self.skolemization_count)
1513 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
1514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1516 GenericKind::Param(ref p) => write!(f, "{:?}", p),
1517 GenericKind::Projection(ref p) => write!(f, "{:?}", p),
1522 impl<'tcx> fmt::Display for GenericKind<'tcx> {
1523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1525 GenericKind::Param(ref p) => write!(f, "{}", p),
1526 GenericKind::Projection(ref p) => write!(f, "{}", p),
1531 impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
1532 pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1534 GenericKind::Param(ref p) => p.to_ty(tcx),
1535 GenericKind::Projection(ref p) => tcx.mk_projection(p.trait_ref.clone(), p.item_name),
1540 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
1541 fn for_each_region(&self, f: &mut FnMut(&'tcx ty::Region)) {
1543 &VerifyBound::AnyRegion(ref rs) |
1544 &VerifyBound::AllRegions(ref rs) => for &r in rs {
1548 &VerifyBound::AnyBound(ref bs) |
1549 &VerifyBound::AllBounds(ref bs) => for b in bs {
1550 b.for_each_region(f);
1555 pub fn must_hold(&self) -> bool {
1557 &VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
1558 &VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1559 &VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1560 &VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1564 pub fn cannot_hold(&self) -> bool {
1566 &VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1567 &VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
1568 &VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1569 &VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1573 pub fn or(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1574 if self.must_hold() || vb.cannot_hold() {
1576 } else if self.cannot_hold() || vb.must_hold() {
1579 VerifyBound::AnyBound(vec![self, vb])
1583 pub fn and(self, vb: VerifyBound<'tcx>) -> VerifyBound<'tcx> {
1584 if self.must_hold() && vb.must_hold() {
1586 } else if self.cannot_hold() && vb.cannot_hold() {
1589 VerifyBound::AllBounds(vec![self, vb])
1593 fn is_met(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
1594 free_regions: &FreeRegionMap,
1595 var_values: &Vec<VarValue<'tcx>>,
1596 min: &'tcx ty::Region)
1599 &VerifyBound::AnyRegion(ref rs) =>
1601 .map(|&r| normalize(tcx, var_values, r))
1602 .any(|r| free_regions.is_subregion_of(tcx, min, r)),
1604 &VerifyBound::AllRegions(ref rs) =>
1606 .map(|&r| normalize(tcx, var_values, r))
1607 .all(|r| free_regions.is_subregion_of(tcx, min, r)),
1609 &VerifyBound::AnyBound(ref bs) =>
1611 .any(|b| b.is_met(tcx, free_regions, var_values, min)),
1613 &VerifyBound::AllBounds(ref bs) =>
1615 .all(|b| b.is_met(tcx, free_regions, var_values, min)),