Skip to content

Commit

Permalink
Auto merge of #41914 - eddyb:region-refactor, r=nikomatsakis
Browse files Browse the repository at this point in the history
rustc: simpler ParameterEnvironment and free regions.

The commits describe the slow transformation but the highlights are:
* `ReEarlyBound` is considered free, with a scope based on the item that defined the lifetime parameter, and the root body of the `RegionMaps` in use, removing the need for `free_substs`
* `liberate_late_bound_regions` and `implicit_region_bound` moved to typeck
* `CodeExtent` not interned at all now - ideally it would be 2 `u32` but it's small anyway

Future work building up on this could include:
* `ParameterEnvironment` becoming just the result of `predicates_of`
  * interning makes my "parent chain" scheme unnecessary
* `implicit_region_bound` could be retrieved from `RegionMaps`
* renaming `CodeExtent` to `Scope`
  * generalizing "call site" to "use site" or something better to include constants
* renaming `RegionMaps` to `ScopeTree` and its API to talk about "parents" explicitly
  • Loading branch information
bors committed May 13, 2017
2 parents 77f1bec + 6da4123 commit 826d8f3
Show file tree
Hide file tree
Showing 69 changed files with 707 additions and 1,100 deletions.
5 changes: 3 additions & 2 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use rustc_data_structures::graph;
use cfg::*;
use middle::region::CodeExtent;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;
Expand Down Expand Up @@ -586,8 +587,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
scope_id: ast::NodeId,
to_index: CFGIndex) {
let mut data = CFGEdgeData { exiting_scopes: vec![] };
let mut scope = self.tcx.node_extent(from_expr.id);
let target_scope = self.tcx.node_extent(scope_id);
let mut scope = CodeExtent::Misc(from_expr.id);
let target_scope = CodeExtent::Misc(scope_id);
let region_maps = self.tcx.region_maps(self.owner_def_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id());
Expand Down
27 changes: 11 additions & 16 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::subst::Kind<'t
}
}

impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tcx> {
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
Expand All @@ -54,7 +54,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tc
db.depth.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
}
ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
def_id.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
Expand Down Expand Up @@ -409,11 +410,6 @@ impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
Free(call_site_scope_data, decl)
});

impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
fn_id,
body_id
});

impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});
Expand All @@ -432,25 +428,24 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
FnPtrAddrCast
});

impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use middle::region::CodeExtentData;
use middle::region::CodeExtent;

mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
CodeExtentData::Misc(node_id) |
CodeExtentData::DestructionScope(node_id) => {
CodeExtent::Misc(node_id) |
CodeExtent::DestructionScope(node_id) => {
node_id.hash_stable(hcx, hasher);
}
CodeExtentData::CallSiteScope { fn_id, body_id } |
CodeExtentData::ParameterScope { fn_id, body_id } => {
fn_id.hash_stable(hcx, hasher);
CodeExtent::CallSiteScope(body_id) |
CodeExtent::ParameterScope(body_id) => {
body_id.hash_stable(hcx, hasher);
}
CodeExtentData::Remainder(block_remainder) => {
CodeExtent::Remainder(block_remainder) => {
block_remainder.hash_stable(hcx, hasher);
}
}
Expand All @@ -466,7 +461,7 @@ impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
custom_kind
});

impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
impl_stable_hash_for!(struct ty::FreeRegion {
scope,
bound_region
});
Expand Down
10 changes: 1 addition & 9 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
return Ok(r);
}

// Early-bound regions should really have been substituted away before
// we get to this point.
ty::ReEarlyBound(..) => {
span_bug!(
self.span,
"Encountered early bound region when generalizing: {:?}",
r);
}

// Always make a fresh region variable for skolemized regions;
// the higher-ranked decision procedures rely on this.
ty::ReSkolemized(..) => { }
Expand All @@ -442,6 +433,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
ty::ReStatic |
ty::ReScope(..) |
ty::ReVar(..) |
ty::ReEarlyBound(..) |
ty::ReFree(..) => {
match self.ambient_variance {
ty::Invariant => return Ok(r),
Expand Down
53 changes: 34 additions & 19 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,19 +151,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
return;
}
};
let scope_decorated_tag = match *scope {
region::CodeExtentData::Misc(_) => tag,
region::CodeExtentData::CallSiteScope { .. } => {
let scope_decorated_tag = match scope {
region::CodeExtent::Misc(_) => tag,
region::CodeExtent::CallSiteScope(_) => {
"scope of call-site for function"
}
region::CodeExtentData::ParameterScope { .. } => {
region::CodeExtent::ParameterScope(_) => {
"scope of function body"
}
region::CodeExtentData::DestructionScope(_) => {
region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
region::CodeExtentData::Remainder(r) => {
region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&new_string[..]
Expand All @@ -172,19 +172,35 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
explain_span(self, scope_decorated_tag, span)
}

ty::ReFree(ref fr) => {
let prefix = match fr.bound_region {
ty::BrAnon(idx) => {
format!("the anonymous lifetime #{} defined on", idx + 1)
ty::ReEarlyBound(_) |
ty::ReFree(_) => {
let scope = match *region {
ty::ReEarlyBound(ref br) => {
self.parent_def_id(br.def_id).unwrap()
}
ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
_ => {
format!("the lifetime {} as defined on",
fr.bound_region)
ty::ReFree(ref fr) => fr.scope,
_ => bug!()
};
let prefix = match *region {
ty::ReEarlyBound(ref br) => {
format!("the lifetime {} as defined on", br.name)
}
ty::ReFree(ref fr) => {
match fr.bound_region {
ty::BrAnon(idx) => {
format!("the anonymous lifetime #{} defined on", idx + 1)
}
ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
_ => {
format!("the lifetime {} as defined on",
fr.bound_region)
}
}
}
_ => bug!()
};

let node = fr.scope.map(|s| s.node_id())
let node = self.hir.as_local_node_id(scope)
.unwrap_or(DUMMY_NODE_ID);
let unknown;
let tag = match self.hir.find(node) {
Expand All @@ -199,12 +215,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
Some(_) => {
unknown = format!("unexpected node ({}) for scope {:?}. \
Please report a bug.",
self.hir.node_to_string(node), fr.scope);
self.hir.node_to_string(node), scope);
&unknown
}
None => {
unknown = format!("unknown node for scope {:?}. \
Please report a bug.", fr.scope);
Please report a bug.", scope);
&unknown
}
};
Expand All @@ -216,8 +232,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

ty::ReEmpty => ("the empty lifetime".to_owned(), None),

ty::ReEarlyBound(ref data) => (data.name.to_string(), None),

// FIXME(#13998) ReSkolemized should probably print like
// ReFree rather than dumping Debug output on the user.
//
Expand Down Expand Up @@ -797,6 +811,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

let mut err = match *sub {
ty::ReEarlyBound(_) |
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReEarlyBound(..) |
ty::ReLateBound(..) => {
// leave bound regions alone
r
}

ty::ReStatic |
ty::ReEarlyBound(..) |
ty::ReFree(_) |
ty::ReScope(_) |
ty::ReVar(_) |
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
-> ty::Region<'tcx> {
// Regions that pre-dated the LUB computation stay as they are.
if !is_var_in_set(new_vars, r0) {
assert!(!r0.is_bound());
assert!(!r0.is_late_bound());
debug!("generalize_region(r0={:?}): not new variable", r0);
return r0;
}
Expand All @@ -288,7 +288,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
debug!("generalize_region(r0={:?}): \
non-new-variables found in {:?}",
r0, tainted);
assert!(!r0.is_bound());
assert!(!r0.is_late_bound());
return r0;
}

Expand Down Expand Up @@ -371,7 +371,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
r0: ty::Region<'tcx>)
-> ty::Region<'tcx> {
if !is_var_in_set(new_vars, r0) {
assert!(!r0.is_bound());
assert!(!r0.is_late_bound());
return r0;
}

Expand Down Expand Up @@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
return rev_lookup(infcx, span, a_map, a_r.unwrap());
} else if a_r.is_none() && b_r.is_none() {
// Not related to bound variables from either fn:
assert!(!r0.is_bound());
assert!(!r0.is_late_bound());
return r0;
} else {
// Other:
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,10 @@ impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
Option<ty::ParameterEnvironment<'tcx>>) {
let item_id = tcx.hir.body_owner(self);
(Some(tcx.typeck_tables_of(tcx.hir.local_def_id(item_id))),
let def_id = tcx.hir.body_owner_def_id(self);
(Some(tcx.typeck_tables_of(def_id)),
None,
Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
Some(tcx.parameter_environment(def_id)))
}
}

Expand Down Expand Up @@ -1009,7 +1009,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

pub fn add_given(&self,
sub: ty::FreeRegion<'tcx>,
sub: ty::Region<'tcx>,
sup: ty::RegionVid)
{
self.region_vars.add_given(sub, sup);
Expand Down Expand Up @@ -1324,7 +1324,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

pub fn resolve_regions_and_report_errors(&self,
region_context: DefId,
region_map: &RegionMaps<'tcx>,
region_map: &RegionMaps,
free_regions: &FreeRegionMap<'tcx>) {
let region_rels = RegionRelations::new(self.tcx,
region_context,
Expand Down
22 changes: 11 additions & 11 deletions src/librustc/infer/region_inference/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,20 +124,20 @@ struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
graph_name: String,
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
node_ids: FxHashMap<Node<'tcx>, usize>,
node_ids: FxHashMap<Node, usize>,
}

#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
enum Node<'tcx> {
enum Node {
RegionVid(ty::RegionVid),
Region(ty::RegionKind<'tcx>),
Region(ty::RegionKind),
}

// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
Constraint(Constraint<'tcx>),
EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>),
EnclScope(CodeExtent, CodeExtent),
}

impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
Expand Down Expand Up @@ -176,7 +176,7 @@ impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
}

impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
type Node = Node<'tcx>;
type Node = Node;
type Edge = Edge<'tcx>;
fn graph_id(&self) -> dot::Id {
dot::Id::new(&*self.graph_name).unwrap()
Expand Down Expand Up @@ -209,7 +209,7 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
}
}

fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
match *c {
Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
(Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
Expand All @@ -222,7 +222,7 @@ fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
}
}

fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
fn edge_to_nodes(e: &Edge) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
Expand All @@ -233,9 +233,9 @@ fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
}

impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
type Node = Node<'tcx>;
type Node = Node;
type Edge = Edge<'tcx>;
fn nodes(&self) -> dot::Nodes<Node<'tcx>> {
fn nodes(&self) -> dot::Nodes<Node> {
let mut set = FxHashSet();
for node in self.node_ids.keys() {
set.insert(*node);
Expand All @@ -250,12 +250,12 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
fn source(&self, edge: &Edge<'tcx>) -> Node {
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
fn target(&self, edge: &Edge<'tcx>) -> Node {
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
Expand Down
Loading

0 comments on commit 826d8f3

Please sign in to comment.