2018-06-27 17:19:43 -04:00
|
|
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2018-06-27 16:46:27 -04:00
|
|
|
use rustc::mir::Location;
|
2018-06-27 18:15:57 -04:00
|
|
|
use rustc::ty::RegionVid;
|
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
|
|
|
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
2018-06-27 16:46:27 -04:00
|
|
|
|
|
|
|
use std::fmt;
|
|
|
|
use syntax_pos::Span;
|
2018-06-27 16:25:41 -04:00
|
|
|
|
|
|
|
#[derive(Clone, Default)]
|
|
|
|
crate struct ConstraintSet {
|
|
|
|
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
|
|
|
|
seen_constraints: FxHashSet<(RegionVid, RegionVid)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ConstraintSet {
|
2018-06-27 17:47:55 -04:00
|
|
|
pub fn push(&mut self, constraint: OutlivesConstraint) {
|
2018-06-27 18:15:57 -04:00
|
|
|
debug!(
|
|
|
|
"add_outlives({:?}: {:?} @ {:?}",
|
|
|
|
constraint.sup, constraint.sub, constraint.point
|
|
|
|
);
|
2018-06-27 17:47:55 -04:00
|
|
|
if constraint.sup == constraint.sub {
|
2018-06-27 16:25:41 -04:00
|
|
|
// 'a: 'a is pretty uninteresting
|
|
|
|
return;
|
|
|
|
}
|
2018-06-27 17:47:55 -04:00
|
|
|
if self.seen_constraints.insert(constraint.dedup_key()) {
|
|
|
|
self.constraints.push(constraint);
|
2018-06-27 16:25:41 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 17:19:43 -04:00
|
|
|
pub fn inner(&self) -> &IndexVec<ConstraintIndex, OutlivesConstraint> {
|
2018-06-27 16:25:41 -04:00
|
|
|
&self.constraints
|
|
|
|
}
|
|
|
|
|
2018-06-27 17:47:55 -04:00
|
|
|
pub fn link(&mut self, len: usize) -> IndexVec<RegionVid, Option<ConstraintIndex>> {
|
|
|
|
let mut map = IndexVec::from_elem_n(None, len);
|
|
|
|
|
|
|
|
for (idx, constraint) in self.constraints.iter_enumerated_mut().rev() {
|
|
|
|
let mut head = &mut map[constraint.sub];
|
|
|
|
debug_assert!(constraint.next.is_none());
|
|
|
|
constraint.next = *head;
|
|
|
|
*head = Some(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
map
|
2018-06-27 16:25:41 -04:00
|
|
|
}
|
2018-06-27 18:15:57 -04:00
|
|
|
|
|
|
|
pub fn each_affected_by_dirty(
|
|
|
|
&self,
|
|
|
|
mut opt_dep_idx: Option<ConstraintIndex>,
|
|
|
|
mut op: impl FnMut(ConstraintIndex),
|
|
|
|
) {
|
|
|
|
while let Some(dep_idx) = opt_dep_idx {
|
|
|
|
op(dep_idx);
|
|
|
|
opt_dep_idx = self.constraints[dep_idx].next;
|
|
|
|
}
|
|
|
|
}
|
2018-06-27 16:25:41 -04:00
|
|
|
}
|
|
|
|
|
2018-06-27 16:46:27 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
pub struct OutlivesConstraint {
|
|
|
|
// NB. The ordering here is not significant for correctness, but
|
|
|
|
// it is for convenience. Before we dump the constraints in the
|
|
|
|
// debugging logs, we sort them, and we'd like the "super region"
|
|
|
|
// to be first, etc. (In particular, span should remain last.)
|
|
|
|
/// The region SUP must outlive SUB...
|
|
|
|
pub sup: RegionVid,
|
|
|
|
|
|
|
|
/// Region that must be outlived.
|
|
|
|
pub sub: RegionVid,
|
|
|
|
|
|
|
|
/// At this location.
|
|
|
|
pub point: Location,
|
|
|
|
|
|
|
|
/// Later on, we thread the constraints onto a linked list
|
|
|
|
/// grouped by their `sub` field. So if you had:
|
|
|
|
///
|
|
|
|
/// Index | Constraint | Next Field
|
|
|
|
/// ----- | ---------- | ----------
|
|
|
|
/// 0 | `'a: 'b` | Some(2)
|
|
|
|
/// 1 | `'b: 'c` | None
|
|
|
|
/// 2 | `'c: 'b` | None
|
|
|
|
pub next: Option<ConstraintIndex>,
|
|
|
|
|
|
|
|
/// Where did this constraint arise?
|
|
|
|
pub span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl OutlivesConstraint {
|
|
|
|
pub fn dedup_key(&self) -> (RegionVid, RegionVid) {
|
|
|
|
(self.sup, self.sub)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for OutlivesConstraint {
|
|
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(
|
|
|
|
formatter,
|
|
|
|
"({:?}: {:?} @ {:?}) due to {:?}",
|
|
|
|
self.sup, self.sub, self.point, self.span
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
|