mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
introduce per-fn RegionMaps
Instead of requesting the region maps for the entire crate, request for a given item etc. Several bits of code were modified to take `&RegionMaps` as input (e.g., the `resolve_regions_and_report_errors()` function). I am not totally happy with this setup -- I *think* I'd rather have the region maps be part of typeck tables -- but at least the `RegionMaps` works in a "parallel" way to `FreeRegionMap`, so it's not too bad. Given that I expect a lot of this code to go away with NLL, I didn't want to invest *too* much energy tweaking it.
This commit is contained in:
parent
c7dc39dbf0
commit
73cd9bde37
@ -15,9 +15,11 @@ use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
|
||||
use hir::{self, PatKind};
|
||||
use hir::def_id::DefId;
|
||||
|
||||
struct CFGBuilder<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
owner_def_id: DefId,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
graph: CFGGraph,
|
||||
fn_exit: CFGIndex,
|
||||
@ -56,6 +58,7 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let mut cfg_builder = CFGBuilder {
|
||||
tcx: tcx,
|
||||
owner_def_id,
|
||||
tables: tables,
|
||||
graph: graph,
|
||||
fn_exit: fn_exit,
|
||||
@ -585,9 +588,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
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 region_maps = self.tcx.region_maps(self.owner_def_id);
|
||||
while scope != target_scope {
|
||||
data.exiting_scopes.push(scope.node_id());
|
||||
scope = self.tcx.region_maps().encl_scope(scope);
|
||||
scope = region_maps.encl_scope(scope);
|
||||
}
|
||||
self.graph.add_edge(from_index, to_index, data);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
WorkProduct(Arc<WorkProductId>),
|
||||
|
||||
// Represents different phases in the compiler.
|
||||
RegionResolveCrate,
|
||||
RegionMaps(D),
|
||||
Coherence,
|
||||
Resolve,
|
||||
CoherenceCheckTrait(D),
|
||||
@ -197,7 +197,6 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
BorrowCheckKrate => Some(BorrowCheckKrate),
|
||||
MirKrate => Some(MirKrate),
|
||||
TypeckBodiesKrate => Some(TypeckBodiesKrate),
|
||||
RegionResolveCrate => Some(RegionResolveCrate),
|
||||
Coherence => Some(Coherence),
|
||||
Resolve => Some(Resolve),
|
||||
Variance => Some(Variance),
|
||||
@ -223,6 +222,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
||||
def_ids.map(MirShim)
|
||||
}
|
||||
BorrowCheck(ref d) => op(d).map(BorrowCheck),
|
||||
RegionMaps(ref d) => op(d).map(RegionMaps),
|
||||
RvalueCheck(ref d) => op(d).map(RvalueCheck),
|
||||
TransCrateItem(ref d) => op(d).map(TransCrateItem),
|
||||
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
|
||||
|
@ -39,7 +39,7 @@ use syntax::codemap::Spanned;
|
||||
use syntax_pos::Span;
|
||||
use hir::*;
|
||||
use hir::def::Def;
|
||||
use hir::map::Map;
|
||||
use hir::map::{self, Map};
|
||||
use super::itemlikevisit::DeepVisitor;
|
||||
|
||||
use std::cmp;
|
||||
@ -140,6 +140,23 @@ impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> {
|
||||
/// to monitor future changes to `Visitor` in case a new method with a
|
||||
/// new default implementation gets introduced.)
|
||||
pub trait Visitor<'v> : Sized {
|
||||
/// Invokes the suitable visitor method for the given `Node`
|
||||
/// extracted from the hir map.
|
||||
fn visit_hir_map_node(&mut self, node: map::Node<'v>) {
|
||||
match node {
|
||||
map::NodeItem(a) => self.visit_item(a),
|
||||
map::NodeForeignItem(a) => self.visit_foreign_item(a),
|
||||
map::NodeTraitItem(a) => self.visit_trait_item(a),
|
||||
map::NodeImplItem(a) => self.visit_impl_item(a),
|
||||
map::NodeExpr(a) => self.visit_expr(a),
|
||||
map::NodeStmt(a) => self.visit_stmt(a),
|
||||
map::NodeTy(a) => self.visit_ty(a),
|
||||
map::NodePat(a) => self.visit_pat(a),
|
||||
map::NodeBlock(a) => self.visit_block(a),
|
||||
_ => bug!("Visitor::visit_hir_map_node() not yet impl for node `{:?}`", node)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Nested items.
|
||||
|
||||
|
@ -572,6 +572,18 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the node is a non-closure function item
|
||||
pub fn is_fn(&self, id: NodeId) -> bool {
|
||||
let entry = if let Some(id) = self.find_entry(id) { id } else { return false };
|
||||
|
||||
match entry {
|
||||
EntryItem(_, &Item { node: ItemFn(..), .. }) |
|
||||
EntryTraitItem(_, &TraitItem { node: TraitItemKind::Method(..), .. }) |
|
||||
EntryImplItem(_, &ImplItem { node: ImplItemKind::Method(..), .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// If there is some error when walking the parents (e.g., a node does not
|
||||
/// have a parent in the map or a node can't be found), then we return the
|
||||
/// last good node id we found. Note that reaching the crate root (id == 0),
|
||||
|
@ -20,7 +20,8 @@ pub use self::region_inference::{GenericKind, VerifyBound};
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use hir;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::free_region::{FreeRegionMap, RegionRelations};
|
||||
use middle::region::RegionMaps;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::McResult;
|
||||
use middle::lang_items;
|
||||
@ -1322,9 +1323,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn resolve_regions_and_report_errors(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
subject_node_id: ast::NodeId) {
|
||||
let errors = self.region_vars.resolve_regions(free_regions, subject_node_id);
|
||||
region_context: DefId,
|
||||
region_map: &RegionMaps<'tcx>,
|
||||
free_regions: &FreeRegionMap<'tcx>) {
|
||||
let region_rels = RegionRelations::new(self.tcx,
|
||||
region_context,
|
||||
region_map,
|
||||
free_regions);
|
||||
let errors = self.region_vars.resolve_regions(®ion_rels);
|
||||
if !self.is_tainted_by_errors() {
|
||||
// As a heuristic, just skip reporting region errors
|
||||
// altogether if other errors have been reported while
|
||||
|
@ -18,7 +18,9 @@
|
||||
/// For clarity, rename the graphviz crate locally to dot.
|
||||
use graphviz as dot;
|
||||
|
||||
use ty::{self, TyCtxt};
|
||||
use hir::def_id::DefIndex;
|
||||
use ty;
|
||||
use middle::free_region::RegionRelations;
|
||||
use middle::region::CodeExtent;
|
||||
use super::Constraint;
|
||||
use infer::SubregionOrigin;
|
||||
@ -32,7 +34,6 @@ use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use syntax::ast;
|
||||
|
||||
fn print_help_message() {
|
||||
println!("\
|
||||
@ -55,18 +56,18 @@ graphs will be printed. \n\
|
||||
|
||||
pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
|
||||
region_vars: &RegionVarBindings<'a, 'gcx, 'tcx>,
|
||||
subject_node: ast::NodeId)
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
|
||||
{
|
||||
let tcx = region_vars.tcx;
|
||||
let context = region_rels.context;
|
||||
|
||||
if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
|
||||
return;
|
||||
}
|
||||
|
||||
let requested_node = env::var("RUST_REGION_GRAPH_NODE")
|
||||
.ok().and_then(|s| s.parse().map(ast::NodeId::new).ok());
|
||||
.ok().and_then(|s| s.parse().map(DefIndex::new).ok());
|
||||
|
||||
if requested_node.is_some() && requested_node != Some(subject_node) {
|
||||
if requested_node.is_some() && requested_node != Some(context.index) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -98,7 +99,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
|
||||
let mut new_str = String::new();
|
||||
for c in output_template.chars() {
|
||||
if c == '%' {
|
||||
new_str.push_str(&subject_node.to_string());
|
||||
new_str.push_str(&context.index.as_usize().to_string());
|
||||
} else {
|
||||
new_str.push(c);
|
||||
}
|
||||
@ -110,7 +111,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
|
||||
};
|
||||
|
||||
let constraints = &*region_vars.constraints.borrow();
|
||||
match dump_region_constraints_to(tcx, constraints, &output_path) {
|
||||
match dump_region_constraints_to(region_rels, constraints, &output_path) {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
let msg = format!("io error dumping region constraints: {}", e);
|
||||
@ -120,8 +121,8 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
|
||||
}
|
||||
|
||||
struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
graph_name: String,
|
||||
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
|
||||
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
|
||||
node_ids: FxHashMap<Node<'tcx>, usize>,
|
||||
}
|
||||
@ -140,8 +141,8 @@ enum Edge<'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
|
||||
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
name: String,
|
||||
fn new(name: String,
|
||||
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
|
||||
map: &'a ConstraintMap<'tcx>)
|
||||
-> ConstraintGraph<'a, 'gcx, 'tcx> {
|
||||
let mut i = 0;
|
||||
@ -159,17 +160,17 @@ impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
|
||||
add_node(n2);
|
||||
}
|
||||
|
||||
tcx.region_maps().each_encl_scope(|sub, sup| {
|
||||
region_rels.region_maps.each_encl_scope(|sub, sup| {
|
||||
add_node(Node::Region(ty::ReScope(sub)));
|
||||
add_node(Node::Region(ty::ReScope(sup)));
|
||||
});
|
||||
}
|
||||
|
||||
ConstraintGraph {
|
||||
tcx: tcx,
|
||||
map,
|
||||
node_ids,
|
||||
region_rels,
|
||||
graph_name: name,
|
||||
map: map,
|
||||
node_ids: node_ids,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,7 +246,7 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
|
||||
fn edges(&self) -> dot::Edges<Edge<'tcx>> {
|
||||
debug!("constraint graph has {} edges", self.map.len());
|
||||
let mut v: Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
|
||||
self.tcx.region_maps().each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
|
||||
self.region_rels.region_maps.each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
|
||||
debug!("region graph has {} edges", v.len());
|
||||
Cow::Owned(v)
|
||||
}
|
||||
@ -263,14 +264,14 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub type ConstraintMap<'tcx> = FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
|
||||
|
||||
fn dump_region_constraints_to<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
map: &ConstraintMap<'tcx>,
|
||||
path: &str)
|
||||
-> io::Result<()> {
|
||||
debug!("dump_region_constraints map (len: {}) path: {}",
|
||||
map.len(),
|
||||
path);
|
||||
let g = ConstraintGraph::new(tcx, format!("region_constraints"), map);
|
||||
let g = ConstraintGraph::new(format!("region_constraints"), region_rels, map);
|
||||
debug!("dump_region_constraints calling render");
|
||||
let mut v = Vec::new();
|
||||
dot::render(&g, &mut v).unwrap();
|
||||
|
@ -22,7 +22,7 @@ use super::unify_key;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
|
||||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::free_region::RegionRelations;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{Region, RegionVid};
|
||||
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
|
||||
@ -33,7 +33,6 @@ use std::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::u32;
|
||||
use syntax::ast;
|
||||
|
||||
mod graphviz;
|
||||
|
||||
@ -892,18 +891,17 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
/// constraints, assuming such values can be found; if they cannot,
|
||||
/// errors are reported.
|
||||
pub fn resolve_regions(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
subject_node: ast::NodeId)
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
|
||||
-> Vec<RegionResolutionError<'tcx>> {
|
||||
debug!("RegionVarBindings: resolve_regions()");
|
||||
let mut errors = vec![];
|
||||
let v = self.infer_variable_values(free_regions, &mut errors, subject_node);
|
||||
let v = self.infer_variable_values(region_rels, &mut errors);
|
||||
*self.values.borrow_mut() = Some(v);
|
||||
errors
|
||||
}
|
||||
|
||||
fn lub_concrete_regions(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
a: Region<'tcx>,
|
||||
b: Region<'tcx>)
|
||||
-> Region<'tcx> {
|
||||
@ -939,7 +937,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
// at least as big as the block fr.scope_id". So, we can
|
||||
// reasonably compare free regions and scopes:
|
||||
if let Some(fr_scope) = fr.scope {
|
||||
let r_id = self.tcx.region_maps().nearest_common_ancestor(fr_scope, s_id);
|
||||
let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
|
||||
if r_id == fr_scope {
|
||||
// if the free region's scope `fr.scope_id` is bigger than
|
||||
// the scope region `s_id`, then the LUB is the free
|
||||
@ -957,12 +955,12 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
// The region corresponding to an outer block is a
|
||||
// subtype of the region corresponding to an inner
|
||||
// block.
|
||||
self.tcx.mk_region(ReScope(
|
||||
self.tcx.region_maps().nearest_common_ancestor(a_id, b_id)))
|
||||
let lub = region_rels.region_maps.nearest_common_ancestor(a_id, b_id);
|
||||
self.tcx.mk_region(ReScope(lub))
|
||||
}
|
||||
|
||||
(&ReFree(_), &ReFree(_)) => {
|
||||
free_regions.lub_free_regions(self.tcx, a, b)
|
||||
region_rels.lub_free_regions(a, b)
|
||||
}
|
||||
|
||||
// For these types, we cannot define any additional
|
||||
@ -996,24 +994,23 @@ type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
fn infer_variable_values(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>,
|
||||
subject: ast::NodeId)
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>)
|
||||
-> Vec<VarValue<'tcx>> {
|
||||
let mut var_data = self.construct_var_data();
|
||||
|
||||
// Dorky hack to cause `dump_constraints` to only get called
|
||||
// if debug mode is enabled:
|
||||
debug!("----() End constraint listing (subject={}) {:?}---",
|
||||
subject,
|
||||
self.dump_constraints(subject));
|
||||
graphviz::maybe_print_constraints_for(self, subject);
|
||||
debug!("----() End constraint listing (context={:?}) {:?}---",
|
||||
region_rels.context,
|
||||
self.dump_constraints(region_rels));
|
||||
graphviz::maybe_print_constraints_for(self, region_rels);
|
||||
|
||||
let graph = self.construct_graph();
|
||||
self.expand_givens(&graph);
|
||||
self.expansion(free_regions, &mut var_data);
|
||||
self.collect_errors(free_regions, &mut var_data, errors);
|
||||
self.collect_var_errors(free_regions, &var_data, &graph, errors);
|
||||
self.expansion(region_rels, &mut var_data);
|
||||
self.collect_errors(region_rels, &mut var_data, errors);
|
||||
self.collect_var_errors(region_rels, &var_data, &graph, errors);
|
||||
var_data
|
||||
}
|
||||
|
||||
@ -1023,9 +1020,9 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn dump_constraints(&self, subject: ast::NodeId) {
|
||||
debug!("----() Start constraint listing (subject={}) ()----",
|
||||
subject);
|
||||
fn dump_constraints(&self, free_regions: &RegionRelations<'a, 'gcx, 'tcx>) {
|
||||
debug!("----() Start constraint listing (context={:?}) ()----",
|
||||
free_regions.context);
|
||||
for (idx, (constraint, _)) in self.constraints.borrow().iter().enumerate() {
|
||||
debug!("Constraint {} => {:?}", idx, constraint);
|
||||
}
|
||||
@ -1056,21 +1053,21 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn expansion(&self, free_regions: &FreeRegionMap<'tcx>, var_values: &mut [VarValue<'tcx>]) {
|
||||
fn expansion(&self, region_rels: &RegionRelations<'a, 'gcx, 'tcx>, var_values: &mut [VarValue<'tcx>]) {
|
||||
self.iterate_until_fixed_point("Expansion", |constraint, origin| {
|
||||
debug!("expansion: constraint={:?} origin={:?}",
|
||||
constraint, origin);
|
||||
match *constraint {
|
||||
ConstrainRegSubVar(a_region, b_vid) => {
|
||||
let b_data = &mut var_values[b_vid.index as usize];
|
||||
self.expand_node(free_regions, a_region, b_vid, b_data)
|
||||
self.expand_node(region_rels, a_region, b_vid, b_data)
|
||||
}
|
||||
ConstrainVarSubVar(a_vid, b_vid) => {
|
||||
match var_values[a_vid.index as usize] {
|
||||
ErrorValue => false,
|
||||
Value(a_region) => {
|
||||
let b_node = &mut var_values[b_vid.index as usize];
|
||||
self.expand_node(free_regions, a_region, b_vid, b_node)
|
||||
self.expand_node(region_rels, a_region, b_vid, b_node)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1085,7 +1082,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn expand_node(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
a_region: Region<'tcx>,
|
||||
b_vid: RegionVid,
|
||||
b_data: &mut VarValue<'tcx>)
|
||||
@ -1108,7 +1105,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
|
||||
match *b_data {
|
||||
Value(cur_region) => {
|
||||
let lub = self.lub_concrete_regions(free_regions, a_region, cur_region);
|
||||
let lub = self.lub_concrete_regions(region_rels, a_region, cur_region);
|
||||
if lub == cur_region {
|
||||
return false;
|
||||
}
|
||||
@ -1132,7 +1129,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
/// cases where the region cannot grow larger than a fixed point)
|
||||
/// and check that they are satisfied.
|
||||
fn collect_errors(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
var_data: &mut Vec<VarValue<'tcx>>,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>) {
|
||||
let constraints = self.constraints.borrow();
|
||||
@ -1146,7 +1143,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ConstrainRegSubReg(sub, sup) => {
|
||||
if free_regions.is_subregion_of(self.tcx, sub, sup) {
|
||||
if region_rels.is_subregion_of(sub, sup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1174,7 +1171,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
// Do not report these errors immediately:
|
||||
// instead, set the variable value to error and
|
||||
// collect them later.
|
||||
if !free_regions.is_subregion_of(self.tcx, a_region, b_region) {
|
||||
if !region_rels.is_subregion_of(a_region, b_region) {
|
||||
debug!("collect_errors: region error at {:?}: \
|
||||
cannot verify that {:?}={:?} <= {:?}",
|
||||
origin,
|
||||
@ -1190,7 +1187,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
for verify in self.verifys.borrow().iter() {
|
||||
debug!("collect_errors: verify={:?}", verify);
|
||||
let sub = normalize(self.tcx, var_data, verify.region);
|
||||
if verify.bound.is_met(self.tcx, free_regions, var_data, sub) {
|
||||
if verify.bound.is_met(region_rels, var_data, sub) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1209,7 +1206,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
/// Go over the variables that were declared to be error variables
|
||||
/// and create a `RegionResolutionError` for each of them.
|
||||
fn collect_var_errors(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
var_data: &[VarValue<'tcx>],
|
||||
graph: &RegionGraph<'tcx>,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>) {
|
||||
@ -1258,7 +1255,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
this portion of the code and think hard about it. =) */
|
||||
|
||||
let node_vid = RegionVid { index: idx as u32 };
|
||||
self.collect_error_for_expanding_node(free_regions,
|
||||
self.collect_error_for_expanding_node(region_rels,
|
||||
graph,
|
||||
&mut dup_vec,
|
||||
node_vid,
|
||||
@ -1311,7 +1308,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn collect_error_for_expanding_node(&self,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
graph: &RegionGraph<'tcx>,
|
||||
dup_vec: &mut [u32],
|
||||
node_idx: RegionVid,
|
||||
@ -1347,7 +1344,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||
|
||||
for lower_bound in &lower_bounds {
|
||||
for upper_bound in &upper_bounds {
|
||||
if !free_regions.is_subregion_of(self.tcx, lower_bound.region, upper_bound.region) {
|
||||
if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
|
||||
let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
|
||||
debug!("region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
|
||||
sup: {:?}",
|
||||
@ -1591,29 +1588,30 @@ impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_met(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
free_regions: &FreeRegionMap<'tcx>,
|
||||
fn is_met(&self,
|
||||
region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
|
||||
var_values: &Vec<VarValue<'tcx>>,
|
||||
min: ty::Region<'tcx>)
|
||||
-> bool {
|
||||
let tcx = region_rels.tcx;
|
||||
match self {
|
||||
&VerifyBound::AnyRegion(ref rs) =>
|
||||
rs.iter()
|
||||
.map(|&r| normalize(tcx, var_values, r))
|
||||
.any(|r| free_regions.is_subregion_of(tcx, min, r)),
|
||||
.any(|r| region_rels.is_subregion_of(min, r)),
|
||||
|
||||
&VerifyBound::AllRegions(ref rs) =>
|
||||
rs.iter()
|
||||
.map(|&r| normalize(tcx, var_values, r))
|
||||
.all(|r| free_regions.is_subregion_of(tcx, min, r)),
|
||||
.all(|r| region_rels.is_subregion_of(min, r)),
|
||||
|
||||
&VerifyBound::AnyBound(ref bs) =>
|
||||
bs.iter()
|
||||
.any(|b| b.is_met(tcx, free_regions, var_values, min)),
|
||||
.any(|b| b.is_met(region_rels, var_values, min)),
|
||||
|
||||
&VerifyBound::AllBounds(ref bs) =>
|
||||
bs.iter()
|
||||
.all(|b| b.is_met(tcx, free_regions, var_values, min)),
|
||||
.all(|b| b.is_met(region_rels, var_values, min)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,19 +270,24 @@ enum PassArgs {
|
||||
|
||||
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
|
||||
context: DefId,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
|
||||
-> Self
|
||||
{
|
||||
ExprUseVisitor::with_options(delegate, infcx, mc::MemCategorizationOptions::default())
|
||||
ExprUseVisitor::with_options(delegate,
|
||||
infcx,
|
||||
context,
|
||||
mc::MemCategorizationOptions::default())
|
||||
}
|
||||
|
||||
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
context: DefId,
|
||||
options: mc::MemCategorizationOptions)
|
||||
-> Self
|
||||
{
|
||||
ExprUseVisitor {
|
||||
mc: mc::MemCategorizationContext::with_options(infcx, options),
|
||||
mc: mc::MemCategorizationContext::with_options(infcx, context, options),
|
||||
delegate: delegate
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,108 @@
|
||||
//! `TransitiveRelation` type and use that to decide when one free
|
||||
//! region outlives another and so forth.
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use middle::region::RegionMaps;
|
||||
use ty::{self, Lift, TyCtxt, Region};
|
||||
use ty::wf::ImpliedBound;
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
|
||||
/// Combines a `RegionMaps` (which governs relationships between
|
||||
/// scopes) and a `FreeRegionMap` (which governs relationships between
|
||||
/// free regions) to yield a complete relation between concrete
|
||||
/// regions.
|
||||
///
|
||||
/// This stuff is a bit convoluted and should be refactored, but as we
|
||||
/// move to NLL it'll all go away anyhow.
|
||||
pub struct RegionRelations<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
/// context used to fetch the region maps
|
||||
pub context: DefId,
|
||||
|
||||
/// region maps for the given context
|
||||
pub region_maps: &'a RegionMaps<'tcx>,
|
||||
|
||||
/// free-region relationships
|
||||
pub free_regions: &'a FreeRegionMap<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
context: DefId,
|
||||
region_maps: &'a RegionMaps<'tcx>,
|
||||
free_regions: &'a FreeRegionMap<'tcx>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tcx,
|
||||
context,
|
||||
region_maps,
|
||||
free_regions,
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether one region is a subregion of another. This is intended to run *after
|
||||
/// inference* and sadly the logic is somewhat duplicated with the code in infer.rs.
|
||||
pub fn is_subregion_of(&self,
|
||||
sub_region: ty::Region<'tcx>,
|
||||
super_region: ty::Region<'tcx>)
|
||||
-> bool {
|
||||
let result = sub_region == super_region || {
|
||||
match (sub_region, super_region) {
|
||||
(&ty::ReEmpty, _) |
|
||||
(_, &ty::ReStatic) =>
|
||||
true,
|
||||
|
||||
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
|
||||
self.region_maps.is_subscope_of(sub_scope, super_scope),
|
||||
|
||||
(&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
|
||||
// 1. It is safe to unwrap `fr.scope` because we
|
||||
// should only ever wind up comparing against
|
||||
// `ReScope` in the context of a method or
|
||||
// body, where `fr.scope` should be `Some`.
|
||||
self.region_maps.is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
|
||||
self.is_static(super_region)
|
||||
}
|
||||
|
||||
(&ty::ReFree(_), &ty::ReFree(_)) =>
|
||||
self.free_regions.relation.contains(&sub_region, &super_region) ||
|
||||
self.is_static(super_region),
|
||||
|
||||
(&ty::ReStatic, &ty::ReFree(_)) =>
|
||||
self.is_static(super_region),
|
||||
|
||||
_ =>
|
||||
false,
|
||||
}
|
||||
};
|
||||
debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
|
||||
sub_region, super_region, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Determines whether this free-region is required to be 'static
|
||||
fn is_static(&self, super_region: ty::Region<'tcx>) -> bool {
|
||||
debug!("is_static(super_region={:?})", super_region);
|
||||
match *super_region {
|
||||
ty::ReStatic => true,
|
||||
ty::ReFree(_) => {
|
||||
let re_static = self.tcx.mk_region(ty::ReStatic);
|
||||
self.free_regions.relation.contains(&re_static, &super_region)
|
||||
}
|
||||
_ => bug!("only free regions should be given to `is_static`")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lub_free_regions(&self,
|
||||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> Region<'tcx> {
|
||||
self.free_regions.lub_free_regions(self.tcx, r_a, r_b)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct FreeRegionMap<'tcx> {
|
||||
// Stores the relation `a < b`, where `a` and `b` are regions.
|
||||
@ -116,61 +214,6 @@ impl<'tcx> FreeRegionMap<'tcx> {
|
||||
debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Determines whether one region is a subregion of another. This is intended to run *after
|
||||
/// inference* and sadly the logic is somewhat duplicated with the code in infer.rs.
|
||||
pub fn is_subregion_of<'a, 'gcx>(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
sub_region: ty::Region<'tcx>,
|
||||
super_region: ty::Region<'tcx>)
|
||||
-> bool {
|
||||
let result = sub_region == super_region || {
|
||||
match (sub_region, super_region) {
|
||||
(&ty::ReEmpty, _) |
|
||||
(_, &ty::ReStatic) =>
|
||||
true,
|
||||
|
||||
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
|
||||
tcx.region_maps().is_subscope_of(sub_scope, super_scope),
|
||||
|
||||
(&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
|
||||
// 1. It is safe to unwrap `fr.scope` because we
|
||||
// should only ever wind up comparing against
|
||||
// `ReScope` in the context of a method or
|
||||
// body, where `fr.scope` should be `Some`.
|
||||
tcx.region_maps().is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
|
||||
self.is_static(tcx, super_region)
|
||||
}
|
||||
|
||||
(&ty::ReFree(_), &ty::ReFree(_)) =>
|
||||
self.relation.contains(&sub_region, &super_region) ||
|
||||
self.is_static(tcx, super_region),
|
||||
|
||||
(&ty::ReStatic, &ty::ReFree(_)) =>
|
||||
self.is_static(tcx, super_region),
|
||||
|
||||
_ =>
|
||||
false,
|
||||
}
|
||||
};
|
||||
debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
|
||||
sub_region, super_region, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Determines whether this free-region is required to be 'static
|
||||
fn is_static<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, super_region: ty::Region<'tcx>)
|
||||
-> bool {
|
||||
debug!("is_static(super_region={:?})", super_region);
|
||||
match *super_region {
|
||||
ty::ReStatic => true,
|
||||
ty::ReFree(_) => {
|
||||
let re_static = tcx.mk_region(ty::ReStatic);
|
||||
self.relation.contains(&re_static, &super_region)
|
||||
}
|
||||
_ => bug!("only free regions should be given to `is_static`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
|
||||
|
@ -70,6 +70,7 @@ pub use self::Note::*;
|
||||
|
||||
use self::Aliasability::*;
|
||||
|
||||
use middle::region::RegionMaps;
|
||||
use hir::def_id::DefId;
|
||||
use hir::map as hir_map;
|
||||
use infer::InferCtxt;
|
||||
@ -286,9 +287,10 @@ impl ast_node for hir::Pat {
|
||||
fn span(&self) -> Span { self.span }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
pub region_maps: Rc<RegionMaps<'tcx>>,
|
||||
options: MemCategorizationOptions,
|
||||
}
|
||||
|
||||
@ -402,16 +404,21 @@ impl MutabilityCategory {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
|
||||
/// Context should be the `DefId` we use to fetch region-maps.
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
context: DefId)
|
||||
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
MemCategorizationContext::with_options(infcx, MemCategorizationOptions::default())
|
||||
MemCategorizationContext::with_options(infcx, context, MemCategorizationOptions::default())
|
||||
}
|
||||
|
||||
pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
context: DefId,
|
||||
options: MemCategorizationOptions)
|
||||
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
let region_maps = infcx.tcx.region_maps(context);
|
||||
MemCategorizationContext {
|
||||
infcx: infcx,
|
||||
region_maps: region_maps,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
@ -786,7 +793,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
match fn_expr.node {
|
||||
hir::ExprClosure(.., body_id, _) => body_id.node_id,
|
||||
hir::ExprClosure(.., body_id, _) => body_id,
|
||||
_ => bug!()
|
||||
}
|
||||
};
|
||||
@ -796,7 +803,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
// The environment of a closure is guaranteed to
|
||||
// outlive any bindings introduced in the body of the
|
||||
// closure itself.
|
||||
scope: Some(self.tcx().item_extent(fn_body_id)),
|
||||
scope: Some(self.tcx().item_extent(fn_body_id.node_id)),
|
||||
bound_region: ty::BrEnv
|
||||
}));
|
||||
|
||||
@ -845,7 +852,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>)
|
||||
{
|
||||
let (scope, old_scope) =
|
||||
self.tcx().region_maps().old_and_new_temporary_scope(self.tcx(), id);
|
||||
self.region_maps.old_and_new_temporary_scope(self.tcx(), id);
|
||||
(self.tcx().mk_region(match scope {
|
||||
Some(scope) => ty::ReScope(scope),
|
||||
None => ty::ReStatic
|
||||
|
@ -29,8 +29,7 @@ use syntax_pos::Span;
|
||||
use ty::TyCtxt;
|
||||
use ty::maps::Providers;
|
||||
|
||||
use hir;
|
||||
use hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use hir; use hir::def_id::DefId;
|
||||
use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
|
||||
use hir::{Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local};
|
||||
|
||||
@ -226,6 +225,9 @@ pub struct RegionMaps<'tcx> {
|
||||
/// which that variable is declared.
|
||||
var_map: NodeMap<CodeExtent<'tcx>>,
|
||||
|
||||
/// maps from a node-id to the associated destruction scope (if any)
|
||||
destruction_scopes: NodeMap<CodeExtent<'tcx>>,
|
||||
|
||||
/// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
|
||||
/// larger than the default. The map goes from the expression id
|
||||
/// to the cleanup scope id. For rvalues not present in this
|
||||
@ -301,11 +303,22 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> {
|
||||
/// arbitrary amounts of stack space. Terminating scopes end
|
||||
/// up being contained in a DestructionScope that contains the
|
||||
/// destructor's execution.
|
||||
terminating_scopes: NodeSet
|
||||
terminating_scopes: NodeSet,
|
||||
}
|
||||
|
||||
|
||||
impl<'tcx> RegionMaps<'tcx> {
|
||||
pub fn new() -> Self {
|
||||
RegionMaps {
|
||||
scope_map: FxHashMap(),
|
||||
destruction_scopes: FxHashMap(),
|
||||
var_map: NodeMap(),
|
||||
rvalue_scopes: NodeMap(),
|
||||
shrunk_rvalue_scopes: NodeMap(),
|
||||
fn_tree: NodeMap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) {
|
||||
for (&child, &parent) in &self.scope_map {
|
||||
e(child, parent)
|
||||
@ -317,6 +330,10 @@ impl<'tcx> RegionMaps<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent<'tcx>> {
|
||||
self.destruction_scopes.get(&n).cloned()
|
||||
}
|
||||
|
||||
/// Records that `sub_fn` is defined within `sup_fn`. These ids
|
||||
/// should be the id of the block that is the fn body, which is
|
||||
/// also the root of the region hierarchy for that fn.
|
||||
@ -1029,18 +1046,18 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
|
||||
body_id: hir::BodyId,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
visitor.cx.parent = Some(visitor.new_code_extent(
|
||||
CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }));
|
||||
|
||||
debug!("region::resolve_fn(id={:?}, \
|
||||
span={:?}, \
|
||||
body.id={:?}, \
|
||||
cx.parent={:?})",
|
||||
span={:?}, \
|
||||
body.id={:?}, \
|
||||
cx.parent={:?})",
|
||||
id,
|
||||
visitor.tcx.sess.codemap().span_to_string(sp),
|
||||
body_id,
|
||||
visitor.cx.parent);
|
||||
|
||||
visitor.cx.parent = Some(visitor.new_code_extent(
|
||||
CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }));
|
||||
|
||||
let fn_decl_scope = visitor.new_code_extent(
|
||||
CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id });
|
||||
|
||||
@ -1086,6 +1103,12 @@ impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
|
||||
let prev = self.region_maps.scope_map.insert(code_extent, p);
|
||||
assert!(prev.is_none());
|
||||
}
|
||||
|
||||
// record the destruction scopes for later so we can query them
|
||||
if let &CodeExtentData::DestructionScope(n) = code_extent {
|
||||
self.region_maps.destruction_scopes.insert(n, code_extent);
|
||||
}
|
||||
|
||||
code_extent
|
||||
}
|
||||
|
||||
@ -1162,47 +1185,44 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc<RegionMaps<'tcx>> {
|
||||
tcx.region_resolve_crate(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
fn region_resolve_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
|
||||
fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId)
|
||||
-> Rc<RegionMaps<'tcx>>
|
||||
{
|
||||
debug_assert!(crate_num == LOCAL_CRATE);
|
||||
let fn_node_id = tcx.hir.as_local_node_id(fn_id)
|
||||
.expect("fn DefId should be for LOCAL_CRATE");
|
||||
let node = tcx.hir.get(fn_node_id);
|
||||
match node {
|
||||
hir_map::NodeItem(_) | hir_map::NodeTraitItem(_) | hir_map::NodeImplItem(_) => { }
|
||||
_ => {
|
||||
let parent_id = tcx.hir.get_parent(fn_node_id);
|
||||
let parent_def_id = tcx.hir.local_def_id(parent_id);
|
||||
return tcx.region_maps(parent_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
let hir_map = &tcx.hir;
|
||||
|
||||
let krate = hir_map.krate();
|
||||
|
||||
let mut maps = RegionMaps {
|
||||
scope_map: FxHashMap(),
|
||||
var_map: NodeMap(),
|
||||
rvalue_scopes: NodeMap(),
|
||||
shrunk_rvalue_scopes: NodeMap(),
|
||||
fn_tree: NodeMap(),
|
||||
};
|
||||
let mut maps = RegionMaps::new();
|
||||
|
||||
{
|
||||
let mut visitor = RegionResolutionVisitor {
|
||||
tcx: tcx,
|
||||
region_maps: &mut maps,
|
||||
map: hir_map,
|
||||
map: &tcx.hir,
|
||||
cx: Context {
|
||||
root_id: None,
|
||||
parent: None,
|
||||
var_parent: None,
|
||||
},
|
||||
terminating_scopes: NodeSet()
|
||||
terminating_scopes: NodeSet(),
|
||||
};
|
||||
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||
visitor.visit_hir_map_node(node);
|
||||
}
|
||||
|
||||
Rc::new(maps)
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
region_resolve_crate,
|
||||
region_maps,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ pub use self::ObligationCauseCode::*;
|
||||
|
||||
use hir;
|
||||
use hir::def_id::DefId;
|
||||
use middle::region::RegionMaps;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use ty::subst::Substs;
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
|
||||
@ -435,9 +436,10 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
|
||||
// FIXME: this is gonna need to be removed ...
|
||||
/// Normalizes the parameter environment, reporting errors if they occur.
|
||||
pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
unnormalized_env: ty::ParameterEnvironment<'tcx>,
|
||||
cause: ObligationCause<'tcx>)
|
||||
-> ty::ParameterEnvironment<'tcx>
|
||||
region_context: DefId,
|
||||
unnormalized_env: ty::ParameterEnvironment<'tcx>,
|
||||
cause: ObligationCause<'tcx>)
|
||||
-> ty::ParameterEnvironment<'tcx>
|
||||
{
|
||||
// I'm not wild about reporting errors here; I'd prefer to
|
||||
// have the errors get reported at a defined place (e.g.,
|
||||
@ -455,7 +457,6 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// can be sure that no errors should occur.
|
||||
|
||||
let span = cause.span;
|
||||
let body_id = cause.body_id;
|
||||
|
||||
debug!("normalize_param_env_or_error(unnormalized_env={:?})",
|
||||
unnormalized_env);
|
||||
@ -492,8 +493,9 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("normalize_param_env_or_error: normalized predicates={:?}",
|
||||
predicates);
|
||||
|
||||
let region_maps = RegionMaps::new();
|
||||
let free_regions = FreeRegionMap::new();
|
||||
infcx.resolve_regions_and_report_errors(&free_regions, body_id);
|
||||
infcx.resolve_regions_and_report_errors(region_context, ®ion_maps, &free_regions);
|
||||
let predicates = match infcx.fully_resolve(&predicates) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(fixup_err) => {
|
||||
|
@ -21,7 +21,7 @@ use hir::map as hir_map;
|
||||
use hir::map::DisambiguatedDefPathData;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::lang_items;
|
||||
use middle::region::{CodeExtent, CodeExtentData, RegionMaps};
|
||||
use middle::region::{CodeExtent, CodeExtentData};
|
||||
use middle::resolve_lifetime;
|
||||
use middle::stability;
|
||||
use mir::Mir;
|
||||
@ -52,7 +52,6 @@ use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::iter;
|
||||
use std::cmp::Ordering;
|
||||
use std::rc::Rc;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{self, Name, NodeId};
|
||||
use syntax::attr;
|
||||
@ -656,12 +655,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.intern_code_extent(CodeExtentData::Misc(n))
|
||||
}
|
||||
|
||||
// TODO this is revealing side-effects of query, bad
|
||||
pub fn opt_destruction_extent(self, n: ast::NodeId) -> Option<CodeExtent<'gcx>> {
|
||||
let s = CodeExtentData::DestructionScope(n);
|
||||
self.code_extent_interner.borrow().get(&s).cloned()
|
||||
}
|
||||
|
||||
// Returns the code extent for an item - the destruction scope.
|
||||
pub fn item_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
|
||||
self.intern_code_extent(CodeExtentData::DestructionScope(n))
|
||||
@ -712,10 +705,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
local as usize == global as usize
|
||||
}
|
||||
|
||||
pub fn region_maps(self) -> Rc<RegionMaps<'tcx>> {
|
||||
self.region_resolve_crate(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
/// Create a type context and call the closure with a `TyCtxt` reference
|
||||
/// to the context. The closure enforces that the type context and any interned
|
||||
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
|
||||
|
@ -292,12 +292,6 @@ impl<'tcx> QueryDescription for queries::def_span<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::region_resolve_crate<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("resolve crate")
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_maps {
|
||||
(<$tcx:tt>
|
||||
$($(#[$attr:meta])*
|
||||
@ -578,7 +572,10 @@ define_maps! { <'tcx>
|
||||
|
||||
[] reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
|
||||
|
||||
[] region_resolve_crate: region_resolve_crate_dep_node(CrateNum) -> Rc<RegionMaps<'tcx>>,
|
||||
/// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body;
|
||||
/// in the case of closures or "inline" expressions, this will be redirected to the enclosing
|
||||
/// fn item.
|
||||
[] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
|
||||
|
||||
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>,
|
||||
|
||||
@ -601,10 +598,6 @@ fn reachability_dep_node(_: CrateNum) -> DepNode<DefId> {
|
||||
DepNode::Reachability
|
||||
}
|
||||
|
||||
fn region_resolve_crate_dep_node(_: CrateNum) -> DepNode<DefId> {
|
||||
DepNode::RegionResolveCrate
|
||||
}
|
||||
|
||||
fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode<DefId> {
|
||||
instance.dep_node()
|
||||
}
|
||||
|
@ -2526,7 +2526,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
let body_id = free_id_outlive.map(|f| f.node_id())
|
||||
.unwrap_or(DUMMY_NODE_ID);
|
||||
let cause = traits::ObligationCause::misc(span, body_id);
|
||||
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
|
||||
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
|
||||
}
|
||||
|
||||
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
|
||||
|
@ -199,7 +199,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
all_loans: all_loans,
|
||||
param_env: &infcx.parameter_environment
|
||||
};
|
||||
euv::ExprUseVisitor::new(&mut clcx, &infcx).consume_body(body);
|
||||
euv::ExprUseVisitor::new(&mut clcx, bccx.owner_def_id, &infcx).consume_body(body);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
@ -238,9 +238,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
//! Like `each_issued_loan()`, but only considers loans that are
|
||||
//! currently in scope.
|
||||
|
||||
let tcx = self.tcx();
|
||||
self.each_issued_loan(scope.node_id(), |loan| {
|
||||
if tcx.region_maps().is_subscope_of(scope, loan.kill_scope) {
|
||||
if self.bccx.region_maps.is_subscope_of(scope, loan.kill_scope) {
|
||||
op(loan)
|
||||
} else {
|
||||
true
|
||||
@ -379,8 +378,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
new_loan);
|
||||
|
||||
// Should only be called for loans that are in scope at the same time.
|
||||
assert!(self.tcx().region_maps().scopes_intersect(old_loan.kill_scope,
|
||||
new_loan.kill_scope));
|
||||
assert!(self.bccx.region_maps.scopes_intersect(old_loan.kill_scope,
|
||||
new_loan.kill_scope));
|
||||
|
||||
self.report_error_if_loan_conflicts_with_restriction(
|
||||
old_loan, new_loan, old_loan, new_loan) &&
|
||||
|
@ -116,7 +116,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
Categorization::Local(local_id) => {
|
||||
self.bccx.tcx.mk_region(ty::ReScope(
|
||||
self.bccx.tcx.region_maps().var_scope(local_id)))
|
||||
self.bccx.region_maps.var_scope(local_id)))
|
||||
}
|
||||
Categorization::StaticItem |
|
||||
Categorization::Deref(.., mc::UnsafePtr(..)) => {
|
||||
|
@ -51,7 +51,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
};
|
||||
|
||||
let body = glcx.bccx.tcx.hir.body(body);
|
||||
euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body);
|
||||
euv::ExprUseVisitor::new(&mut glcx, bccx.owner_def_id, &infcx).consume_body(body);
|
||||
|
||||
glcx.report_potential_errors();
|
||||
let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
|
||||
@ -458,7 +458,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
||||
//! notably method arguments, the loan may be introduced only
|
||||
//! later, once it comes into scope.
|
||||
|
||||
if self.bccx.tcx.region_maps().is_subscope_of(borrow_scope, loan_scope) {
|
||||
if self.bccx.region_maps.is_subscope_of(borrow_scope, loan_scope) {
|
||||
borrow_scope
|
||||
} else {
|
||||
loan_scope
|
||||
@ -488,12 +488,11 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
||||
//! with immutable `&` pointers, because borrows of such pointers
|
||||
//! do not require restrictions and hence do not cause a loan.
|
||||
|
||||
let lexical_scope = lp.kill_scope(self.bccx.tcx);
|
||||
let rm = &self.bccx.tcx.region_maps();
|
||||
if rm.is_subscope_of(lexical_scope, loan_scope) {
|
||||
let lexical_scope = lp.kill_scope(self.bccx);
|
||||
if self.bccx.region_maps.is_subscope_of(lexical_scope, loan_scope) {
|
||||
lexical_scope
|
||||
} else {
|
||||
assert!(self.bccx.tcx.region_maps().is_subscope_of(loan_scope, lexical_scope));
|
||||
assert!(self.bccx.region_maps.is_subscope_of(loan_scope, lexical_scope));
|
||||
loan_scope
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,8 @@ use rustc::middle::expr_use_visitor as euv;
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
use rustc::middle::mem_categorization::Categorization;
|
||||
use rustc::middle::mem_categorization::ImmutabilityBlame;
|
||||
use rustc::middle::region;
|
||||
use rustc::middle::region::{self, RegionMaps};
|
||||
use rustc::middle::free_region::RegionRelations;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
@ -88,11 +89,8 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
|
||||
let body_id = tcx.hir.body_owned_by(owner_id);
|
||||
let attributes = tcx.get_attrs(owner_def_id);
|
||||
let tables = tcx.typeck_tables_of(owner_def_id);
|
||||
|
||||
let mut bccx = &mut BorrowckCtxt {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
};
|
||||
let region_maps = tcx.region_maps(owner_def_id);
|
||||
let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
|
||||
|
||||
let body = bccx.tcx.hir.body(body_id);
|
||||
|
||||
@ -149,7 +147,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
|
||||
loan_dfcx.propagate(cfg, body);
|
||||
|
||||
let flowed_moves = move_data::FlowedMoveData::new(move_data,
|
||||
this.tcx,
|
||||
this,
|
||||
cfg,
|
||||
id_range,
|
||||
body);
|
||||
@ -170,11 +168,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
|
||||
let owner_id = tcx.hir.body_owner(body_id);
|
||||
let owner_def_id = tcx.hir.local_def_id(owner_id);
|
||||
let tables = tcx.typeck_tables_of(owner_def_id);
|
||||
|
||||
let mut bccx = BorrowckCtxt {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
};
|
||||
let region_maps = tcx.region_maps(owner_def_id);
|
||||
let mut bccx = BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
|
||||
|
||||
let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body_id);
|
||||
(bccx, dataflow_data)
|
||||
@ -189,6 +184,10 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
|
||||
// tables for the current thing we are checking; set to
|
||||
// Some in `borrowck_fn` and cleared later
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
|
||||
region_maps: Rc<RegionMaps<'tcx>>,
|
||||
|
||||
owner_def_id: DefId,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -312,15 +311,15 @@ pub fn closure_to_block(closure_id: ast::NodeId,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LoanPath<'tcx> {
|
||||
pub fn kill_scope(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> region::CodeExtent<'tcx> {
|
||||
pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> {
|
||||
match self.kind {
|
||||
LpVar(local_id) => tcx.region_maps().var_scope(local_id),
|
||||
LpVar(local_id) => bccx.region_maps.var_scope(local_id),
|
||||
LpUpvar(upvar_id) => {
|
||||
let block_id = closure_to_block(upvar_id.closure_expr_id, tcx);
|
||||
tcx.node_extent(block_id)
|
||||
let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
|
||||
bccx.tcx.node_extent(block_id)
|
||||
}
|
||||
LpDowncast(ref base, _) |
|
||||
LpExtend(ref base, ..) => base.kill_scope(tcx),
|
||||
LpExtend(ref base, ..) => base.kill_scope(bccx),
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,7 +478,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
r_sup: ty::Region<'tcx>)
|
||||
-> bool
|
||||
{
|
||||
self.tables.free_region_map.is_subregion_of(self.tcx, r_sub, r_sup)
|
||||
let region_rels = RegionRelations::new(self.tcx,
|
||||
self.owner_def_id,
|
||||
&self.region_maps,
|
||||
&self.tables.free_region_map);
|
||||
region_rels.is_subregion_of(r_sub, r_sup)
|
||||
}
|
||||
|
||||
pub fn report(&self, err: BckError<'tcx>) {
|
||||
|
@ -523,7 +523,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
/// Moves are generated by moves and killed by assignments and
|
||||
/// scoping. Assignments are generated by assignment to variables and
|
||||
/// killed by scoping. See `README.md` for more details.
|
||||
fn add_gen_kills(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn add_gen_kills(&self,
|
||||
bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
dfcx_moves: &mut MoveDataFlow,
|
||||
dfcx_assign: &mut AssignDataFlow) {
|
||||
for (i, the_move) in self.moves.borrow().iter().enumerate() {
|
||||
@ -546,7 +547,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
for path in self.paths.borrow().iter() {
|
||||
match path.loan_path.kind {
|
||||
LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
|
||||
let kill_scope = path.loan_path.kill_scope(tcx);
|
||||
let kill_scope = path.loan_path.kill_scope(bccx);
|
||||
let path = *self.path_map.borrow().get(&path.loan_path).unwrap();
|
||||
self.kill_moves(path, kill_scope.node_id(),
|
||||
KillFrom::ScopeEnd, dfcx_moves);
|
||||
@ -561,7 +562,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
let lp = self.path_loan_path(assignment.path);
|
||||
match lp.kind {
|
||||
LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
|
||||
let kill_scope = lp.kill_scope(tcx);
|
||||
let kill_scope = lp.kill_scope(bccx);
|
||||
dfcx_assign.add_kill(KillFrom::ScopeEnd,
|
||||
kill_scope.node_id(),
|
||||
assignment_index);
|
||||
@ -652,11 +653,13 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
|
||||
impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
|
||||
pub fn new(move_data: MoveData<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
cfg: &cfg::CFG,
|
||||
id_range: IdRange,
|
||||
body: &hir::Body)
|
||||
-> FlowedMoveData<'a, 'tcx> {
|
||||
let tcx = bccx.tcx;
|
||||
|
||||
let mut dfcx_moves =
|
||||
DataFlowContext::new(tcx,
|
||||
"flowed_move_data_moves",
|
||||
@ -676,7 +679,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
|
||||
|
||||
move_data.fixup_fragment_sets(tcx);
|
||||
|
||||
move_data.add_gen_kills(tcx,
|
||||
move_data.add_gen_kills(bccx,
|
||||
&mut dfcx_moves,
|
||||
&mut dfcx_assign);
|
||||
|
||||
|
@ -14,6 +14,7 @@ use _match::WitnessPreference::*;
|
||||
|
||||
use pattern::{Pattern, PatternContext, PatternError, PatternKind};
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
|
||||
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
@ -45,9 +46,12 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> {
|
||||
b: hir::BodyId, s: Span, id: ast::NodeId) {
|
||||
intravisit::walk_fn(self, fk, fd, b, s, id);
|
||||
|
||||
let region_context = self.tcx.hir.local_def_id(id);
|
||||
|
||||
MatchVisitor {
|
||||
tcx: self.tcx,
|
||||
tables: self.tcx.body_tables(b),
|
||||
region_context: region_context,
|
||||
param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
|
||||
}.visit_body(self.tcx.hir.body(b));
|
||||
}
|
||||
@ -64,6 +68,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn
|
||||
|
||||
struct MatchVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
region_context: DefId,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
param_env: &'a ty::ParameterEnvironment<'tcx>
|
||||
}
|
||||
@ -517,7 +522,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
|
||||
let mut checker = MutationChecker {
|
||||
cx: cx,
|
||||
};
|
||||
ExprUseVisitor::new(&mut checker, &infcx).walk_expr(guard);
|
||||
ExprUseVisitor::new(&mut checker, cx.region_context, &infcx).walk_expr(guard);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -924,10 +924,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
"load_dep_graph",
|
||||
|| rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
|
||||
|
||||
time(time_passes,
|
||||
"region resolution",
|
||||
|| middle::region::resolve_crate(tcx));
|
||||
|
||||
time(time_passes, "stability index", || {
|
||||
tcx.stability.borrow_mut().build(tcx)
|
||||
});
|
||||
|
@ -155,7 +155,8 @@ fn test_env<F>(source_string: &str,
|
||||
|
||||
body(Env { infcx: &infcx });
|
||||
let free_regions = FreeRegionMap::new();
|
||||
infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
|
||||
let def_id = tcx.hir.map.local_def_id(ast::CRATE_NODE_ID);
|
||||
infcx.resolve_regions_and_report_errors(def_id, ®ion_map, &free_regions);
|
||||
assert_eq!(tcx.sess.err_count(), expected_err_count);
|
||||
});
|
||||
});
|
||||
|
@ -202,7 +202,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) {
|
||||
let local_id = self.var_indices[&var];
|
||||
let var_ty = self.local_decls[local_id].ty;
|
||||
let extent = self.hir.tcx().region_maps().var_scope(var);
|
||||
let extent = self.hir.region_maps.var_scope(var);
|
||||
self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty);
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
|
||||
let tcx = hir.tcx();
|
||||
let span = tcx.hir.span(fn_id);
|
||||
let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
|
||||
let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty);
|
||||
|
||||
let call_site_extent =
|
||||
tcx.intern_code_extent(
|
||||
@ -202,11 +202,10 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let ty = hir.tables().expr_ty_adjusted(ast_expr);
|
||||
let owner_id = tcx.hir.body_owner(body_id);
|
||||
let span = tcx.hir.span(owner_id);
|
||||
let mut builder = Builder::new(hir, span, 0, ty);
|
||||
let mut builder = Builder::new(hir.clone(), span, 0, ty);
|
||||
|
||||
let region_maps = tcx.region_maps();
|
||||
let extent = region_maps.temporary_scope(tcx, ast_expr.id)
|
||||
.unwrap_or(tcx.item_extent(owner_id));
|
||||
let extent = hir.region_maps.temporary_scope(tcx, ast_expr.id)
|
||||
.unwrap_or(tcx.item_extent(owner_id));
|
||||
let mut block = START_BLOCK;
|
||||
let _ = builder.in_scope(extent, block, |builder| {
|
||||
let expr = builder.hir.mirror(ast_expr);
|
||||
|
@ -84,7 +84,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
block: &'tcx hir::Block)
|
||||
-> ExprRef<'tcx> {
|
||||
let block_ty = cx.tables().node_id_to_type(block.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, block.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id);
|
||||
let expr = Expr {
|
||||
ty: block_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
|
@ -26,7 +26,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
type Output = Expr<'tcx>;
|
||||
|
||||
fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, self.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id);
|
||||
let expr_extent = cx.tcx.node_extent(self.id);
|
||||
|
||||
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
|
||||
@ -216,7 +216,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
};
|
||||
|
||||
// Finally, create a destruction scope, if any.
|
||||
if let Some(extent) = cx.tcx.opt_destruction_extent(self.id) {
|
||||
if let Some(extent) = cx.region_maps.opt_destruction_extent(self.id) {
|
||||
expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
temp_lifetime_was_shrunk: was_shrunk,
|
||||
@ -238,7 +238,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
expr: &'tcx hir::Expr)
|
||||
-> Expr<'tcx> {
|
||||
let expr_ty = cx.tables().expr_ty(expr);
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, expr.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
|
||||
|
||||
let kind = match expr.node {
|
||||
// Here comes the interesting stuff:
|
||||
@ -707,7 +707,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
method_call: ty::MethodCall)
|
||||
-> Expr<'tcx> {
|
||||
let callee = cx.tables().method_map[&method_call];
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, expr.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
|
||||
Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
temp_lifetime_was_shrunk: was_shrunk,
|
||||
@ -791,7 +791,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
def: Def)
|
||||
-> ExprKind<'tcx> {
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, expr.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
|
||||
|
||||
match def {
|
||||
Def::Local(def_id) => {
|
||||
@ -979,7 +979,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
PassArgs::ByRef => {
|
||||
let region = cx.tcx.node_scope_region(expr.id);
|
||||
let (temp_lifetime, was_shrunk) =
|
||||
cx.tcx.region_maps().temporary_scope2(cx.tcx, expr.id);
|
||||
cx.region_maps.temporary_scope2(cx.tcx, expr.id);
|
||||
argrefs.extend(args.iter()
|
||||
.map(|arg| {
|
||||
let arg_ty = cx.tables().expr_ty_adjusted(arg);
|
||||
@ -1031,7 +1031,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
|
||||
// construct the complete expression `foo()` for the overloaded call,
|
||||
// which will yield the &T type
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, expr.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
|
||||
let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
|
||||
let ref_expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
@ -1056,7 +1056,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
closure_expr_id: closure_expr.id,
|
||||
};
|
||||
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
|
||||
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps().temporary_scope2(cx.tcx, closure_expr.id);
|
||||
let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id);
|
||||
let var_ty = cx.tables().node_id_to_type(id_var);
|
||||
let captured_var = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
|
@ -22,17 +22,20 @@ use rustc_const_eval::ConstContext;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::middle::region::RegionMaps;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use rustc::hir;
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
pub region_maps: Rc<RegionMaps<'tcx>>,
|
||||
constness: hir::Constness,
|
||||
|
||||
/// True if this constant/function needs overflow checks.
|
||||
@ -51,7 +54,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
MirSource::Promoted(..) => bug!(),
|
||||
};
|
||||
|
||||
let attrs = infcx.tcx.hir.attrs(src.item_id());
|
||||
let tcx = infcx.tcx;
|
||||
let src_id = src.item_id();
|
||||
let src_def_id = tcx.hir.local_def_id(src_id);
|
||||
|
||||
let region_maps = tcx.region_maps(src_def_id);
|
||||
|
||||
let attrs = tcx.hir.attrs(src_id);
|
||||
|
||||
// Some functions always have overflow checks enabled,
|
||||
// however, they may not get codegen'd, depending on
|
||||
@ -60,17 +69,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
.any(|item| item.check_name("rustc_inherit_overflow_checks"));
|
||||
|
||||
// Respect -C overflow-checks.
|
||||
check_overflow |= infcx.tcx.sess.overflow_checks();
|
||||
check_overflow |= tcx.sess.overflow_checks();
|
||||
|
||||
// Constants and const fn's always need overflow checks.
|
||||
check_overflow |= constness == hir::Constness::Const;
|
||||
|
||||
Cx {
|
||||
tcx: infcx.tcx,
|
||||
infcx: infcx,
|
||||
constness: constness,
|
||||
check_overflow: check_overflow,
|
||||
}
|
||||
Cx { tcx, infcx, region_maps, constness, check_overflow }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let outer_tables = self.tables;
|
||||
self.tables = self.tcx.typeck_tables_of(self.tcx.hir.local_def_id(item_id));
|
||||
let item_def_id = self.tcx.hir.local_def_id(item_id);
|
||||
self.tables = self.tcx.typeck_tables_of(item_def_id);
|
||||
|
||||
let body = self.tcx.hir.body(body_id);
|
||||
if !self.in_fn {
|
||||
@ -140,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||
let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
|
||||
let param_env = infcx.parameter_environment.clone();
|
||||
let outer_penv = mem::replace(&mut self.param_env, param_env);
|
||||
euv::ExprUseVisitor::new(self, &infcx).consume_body(body);
|
||||
euv::ExprUseVisitor::new(self, item_def_id, &infcx).consume_body(body);
|
||||
outer_penv
|
||||
});
|
||||
|
||||
|
@ -11,13 +11,13 @@
|
||||
use rustc::hir::{self, ImplItemKind, TraitItemKind};
|
||||
use rustc::infer::{self, InferOk};
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::middle::region::RegionMaps;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
use rustc::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::util::common::ErrorReported;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use super::{Inherited, FnCtxt};
|
||||
@ -30,14 +30,12 @@ use astconv::ExplicitSelf;
|
||||
///
|
||||
/// - impl_m: type of the method we are checking
|
||||
/// - impl_m_span: span to use for reporting errors
|
||||
/// - impl_m_body_id: id of the method body
|
||||
/// - trait_m: the method in the trait
|
||||
/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
|
||||
|
||||
pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
trait_item_span: Option<Span>,
|
||||
@ -72,7 +70,6 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
if let Err(ErrorReported) = compare_predicate_entailment(tcx,
|
||||
impl_m,
|
||||
impl_m_span,
|
||||
impl_m_body_id,
|
||||
trait_m,
|
||||
impl_trait_ref,
|
||||
old_broken_mode) {
|
||||
@ -83,21 +80,25 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
impl_m_body_id: ast::NodeId,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
old_broken_mode: bool)
|
||||
-> Result<(), ErrorReported> {
|
||||
let trait_to_impl_substs = impl_trait_ref.substs;
|
||||
|
||||
// This node-id should be used for the `body_id` field on each
|
||||
// `ObligationCause` (and the `FnCtxt`). This is what
|
||||
// `regionck_item` expects.
|
||||
let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap();
|
||||
|
||||
let cause = ObligationCause {
|
||||
span: impl_m_span,
|
||||
body_id: impl_m_body_id,
|
||||
body_id: impl_m_node_id,
|
||||
code: ObligationCauseCode::CompareImplMethodObligation {
|
||||
item_name: impl_m.name,
|
||||
impl_item_def_id: impl_m.def_id,
|
||||
trait_item_def_id: trait_m.def_id,
|
||||
lint_id: if !old_broken_mode { Some(impl_m_body_id) } else { None },
|
||||
lint_id: if !old_broken_mode { Some(impl_m_node_id) } else { None },
|
||||
},
|
||||
};
|
||||
|
||||
@ -166,7 +167,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
// Create a parameter environment that represents the implementation's
|
||||
// method.
|
||||
let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap();
|
||||
let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id);
|
||||
|
||||
// Create mapping from impl to skolemized.
|
||||
@ -217,9 +217,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
|
||||
// The key step here is to update the caller_bounds's predicates to be
|
||||
// the new hybrid bounds we computed.
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
|
||||
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
|
||||
let trait_param_env = traits::normalize_param_env_or_error(tcx,
|
||||
impl_m.def_id,
|
||||
trait_param_env,
|
||||
normalize_cause.clone());
|
||||
|
||||
@ -275,7 +276,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_sig.subst(tcx, impl_to_skol_substs);
|
||||
let impl_sig =
|
||||
inh.normalize_associated_types_in(impl_m_span,
|
||||
impl_m_body_id,
|
||||
impl_m_node_id,
|
||||
&impl_sig);
|
||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
|
||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||
@ -287,7 +288,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_sig.subst(tcx, trait_to_skol_substs);
|
||||
let trait_sig =
|
||||
inh.normalize_associated_types_in(impl_m_span,
|
||||
impl_m_body_id,
|
||||
impl_m_node_id,
|
||||
&trait_sig);
|
||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig));
|
||||
|
||||
@ -349,13 +350,14 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// region obligations that get overlooked. The right
|
||||
// thing to do is the code below. But we keep this old
|
||||
// pass around temporarily.
|
||||
let region_maps = RegionMaps::new();
|
||||
let mut free_regions = FreeRegionMap::new();
|
||||
free_regions.relate_free_regions_from_predicates(
|
||||
&infcx.parameter_environment.caller_bounds);
|
||||
infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id);
|
||||
infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions);
|
||||
} else {
|
||||
let fcx = FnCtxt::new(&inh, impl_m_body_id);
|
||||
fcx.regionck_item(impl_m_body_id, impl_m_span, &[]);
|
||||
let fcx = FnCtxt::new(&inh, impl_m_node_id);
|
||||
fcx.regionck_item(impl_m_node_id, impl_m_span, &[]);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -13,7 +13,7 @@ use check::regionck::RegionCtxt;
|
||||
use hir::def_id::DefId;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use rustc::infer::{self, InferOk};
|
||||
use middle::region;
|
||||
use rustc::middle::region::{self, RegionMaps};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::traits::{self, ObligationCause, Reveal};
|
||||
@ -116,8 +116,9 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
let region_maps = RegionMaps::new();
|
||||
let free_regions = FreeRegionMap::new();
|
||||
infcx.resolve_regions_and_report_errors(&free_regions, drop_impl_node_id);
|
||||
infcx.resolve_regions_and_report_errors(drop_impl_did, ®ion_maps, &free_regions);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -278,7 +279,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
|
||||
ty, scope);
|
||||
|
||||
|
||||
let parent_scope = match rcx.tcx.region_maps().opt_encl_scope(scope) {
|
||||
let parent_scope = match rcx.region_maps.opt_encl_scope(scope) {
|
||||
Some(parent_scope) => parent_scope,
|
||||
// If no enclosing scope, then it must be the root scope
|
||||
// which cannot be outlived.
|
||||
|
@ -1237,14 +1237,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
err.emit()
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Method(_, body_id) => {
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id);
|
||||
if ty_trait_item.kind == ty::AssociatedKind::Method {
|
||||
let err_count = tcx.sess.err_count();
|
||||
compare_impl_method(tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
body_id.node_id,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
trait_span,
|
||||
@ -1254,7 +1253,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
compare_impl_method(tcx,
|
||||
&ty_impl_item,
|
||||
impl_item.span,
|
||||
body_id.node_id,
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
trait_span,
|
||||
|
@ -87,7 +87,8 @@ use check::FnCtxt;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::Categorization;
|
||||
use middle::region::{self, CodeExtent};
|
||||
use middle::region::{self, CodeExtent, RegionMaps};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, MethodCall, TypeFoldable};
|
||||
@ -97,6 +98,7 @@ use rustc::ty::wf::ImpliedBound;
|
||||
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
@ -112,8 +114,9 @@ macro_rules! ignore_err {
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn regionck_expr(&self, body: &'gcx hir::Body) {
|
||||
let subject = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let id = body.value.id;
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(id));
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(subject));
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_body(body);
|
||||
@ -132,7 +135,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
wf_tys: &[Ty<'tcx>]) {
|
||||
debug!("regionck_item(item.id={:?}, wf_tys={:?}", item_id, wf_tys);
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(item_id), item_id, Subject(item_id));
|
||||
let subject = self.tcx.hir.local_def_id(item_id);
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(item_id), item_id, Subject(subject));
|
||||
rcx.free_region_map.relate_free_regions_from_predicates(
|
||||
&self.parameter_environment.caller_bounds);
|
||||
rcx.relate_free_regions(wf_tys, item_id, span);
|
||||
@ -144,8 +148,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn_id: ast::NodeId,
|
||||
body: &'gcx hir::Body) {
|
||||
debug!("regionck_fn(id={})", fn_id);
|
||||
let subject = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let node_id = body.value.id;
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(fn_id));
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(subject));
|
||||
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
@ -173,6 +178,8 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
|
||||
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
|
||||
|
||||
pub region_maps: Rc<RegionMaps<'tcx>>,
|
||||
|
||||
free_region_map: FreeRegionMap<'tcx>,
|
||||
|
||||
// id of innermost fn body id
|
||||
@ -185,7 +192,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
repeating_scope: ast::NodeId,
|
||||
|
||||
// id of AST node being analyzed (the subject of the analysis).
|
||||
subject: ast::NodeId,
|
||||
subject_def_id: DefId,
|
||||
|
||||
}
|
||||
|
||||
@ -197,19 +204,21 @@ impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub struct RepeatingScope(ast::NodeId);
|
||||
pub struct Subject(ast::NodeId);
|
||||
pub struct Subject(DefId);
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
RepeatingScope(initial_repeating_scope): RepeatingScope,
|
||||
initial_body_id: ast::NodeId,
|
||||
Subject(subject): Subject) -> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
let region_maps = fcx.tcx.region_maps(subject);
|
||||
RegionCtxt {
|
||||
fcx: fcx,
|
||||
region_maps: region_maps,
|
||||
repeating_scope: initial_repeating_scope,
|
||||
body_id: initial_body_id,
|
||||
call_site_scope: None,
|
||||
subject: subject,
|
||||
subject_def_id: subject,
|
||||
region_bound_pairs: Vec::new(),
|
||||
free_region_map: FreeRegionMap::new(),
|
||||
}
|
||||
@ -418,14 +427,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn resolve_regions_and_report_errors(&self) {
|
||||
let subject_node_id = self.subject;
|
||||
|
||||
self.fcx.resolve_regions_and_report_errors(&self.free_region_map,
|
||||
subject_node_id);
|
||||
self.fcx.resolve_regions_and_report_errors(self.subject_def_id,
|
||||
&self.region_maps,
|
||||
&self.free_region_map);
|
||||
}
|
||||
|
||||
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
|
||||
let tcx = self.tcx;
|
||||
debug!("regionck::visit_pat(pat={:?})", pat);
|
||||
pat.each_binding(|_, id, span, _| {
|
||||
// If we have a variable that contains region'd data, that
|
||||
@ -451,7 +458,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
// that the lifetime of any regions that appear in a
|
||||
// variable's type enclose at least the variable's scope.
|
||||
|
||||
let var_scope = tcx.region_maps().var_scope(id);
|
||||
let var_scope = self.region_maps.var_scope(id);
|
||||
let var_region = self.tcx.mk_region(ty::ReScope(var_scope));
|
||||
|
||||
let origin = infer::BindingTypeIsNotValidAtDecl(span);
|
||||
@ -570,7 +577,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
// If necessary, constrain destructors in the unadjusted form of this
|
||||
// expression.
|
||||
let cmt_result = {
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
mc.cat_expr_unadjusted(expr)
|
||||
};
|
||||
match cmt_result {
|
||||
@ -587,7 +594,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
// If necessary, constrain destructors in this expression. This will be
|
||||
// the adjusted form if there is an adjustment.
|
||||
let cmt_result = {
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
mc.cat_expr(expr)
|
||||
};
|
||||
match cmt_result {
|
||||
@ -949,7 +956,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
r, m);
|
||||
|
||||
{
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
|
||||
debug!("constrain_autoderefs: self_cmt={:?}",
|
||||
self_cmt);
|
||||
@ -1061,7 +1068,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
|
||||
|
||||
let cmt = {
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
ignore_err!(mc.cat_expr(base))
|
||||
};
|
||||
|
||||
@ -1079,7 +1086,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
None => { return; }
|
||||
Some(ref expr) => &**expr,
|
||||
};
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = &mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
|
||||
self.link_pattern(mc, discr_cmt, &local.pat);
|
||||
}
|
||||
@ -1089,7 +1096,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
/// linked to the lifetime of its guarantor (if any).
|
||||
fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
|
||||
debug!("regionck::for_match()");
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = &mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
let discr_cmt = ignore_err!(mc.cat_expr(discr));
|
||||
debug!("discr_cmt={:?}", discr_cmt);
|
||||
for arm in arms {
|
||||
@ -1104,7 +1111,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
/// linked to the lifetime of its guarantor (if any).
|
||||
fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) {
|
||||
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = &mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
for arg in args {
|
||||
let arg_ty = self.node_ty(arg.id);
|
||||
let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
|
||||
@ -1121,13 +1128,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found
|
||||
/// in the discriminant, if needed.
|
||||
fn link_pattern<'t>(&self,
|
||||
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
||||
mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
||||
discr_cmt: mc::cmt<'tcx>,
|
||||
root_pat: &hir::Pat) {
|
||||
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
|
||||
discr_cmt,
|
||||
root_pat);
|
||||
let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| {
|
||||
let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| {
|
||||
match sub_pat.node {
|
||||
// `ref x` pattern
|
||||
PatKind::Binding(hir::BindByRef(mutbl), ..) => {
|
||||
@ -1147,7 +1154,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
autoref: &adjustment::AutoBorrow<'tcx>)
|
||||
{
|
||||
debug!("link_autoref(autoderefs={}, autoref={:?})", autoderefs, autoref);
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
|
||||
debug!("expr_cmt={:?}", expr_cmt);
|
||||
|
||||
@ -1171,7 +1178,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
callee_scope: CodeExtent<'tcx>) {
|
||||
debug!("link_by_ref(expr={:?}, callee_scope={:?})",
|
||||
expr, callee_scope);
|
||||
let mc = mc::MemCategorizationContext::new(self);
|
||||
let mc = mc::MemCategorizationContext::new(self, self.subject_def_id);
|
||||
let expr_cmt = ignore_err!(mc.cat_expr(expr));
|
||||
let borrow_region = self.tcx.mk_region(ty::ReScope(callee_scope));
|
||||
self.link_region(expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
|
||||
|
@ -164,9 +164,11 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id());
|
||||
|
||||
{
|
||||
let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id());
|
||||
let mut euv =
|
||||
euv::ExprUseVisitor::with_options(self,
|
||||
self.fcx,
|
||||
body_owner_def_id,
|
||||
mc::MemCategorizationOptions {
|
||||
during_closure_kind_inference: true
|
||||
});
|
||||
|
@ -12,6 +12,7 @@
|
||||
//! up data structures required by type-checking/translation.
|
||||
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::middle::region::RegionMaps;
|
||||
use rustc::middle::lang_items::UnsizeTraitLangItem;
|
||||
|
||||
use rustc::traits::{self, ObligationCause, Reveal};
|
||||
@ -342,10 +343,11 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
let region_maps = RegionMaps::new();
|
||||
let mut free_regions = FreeRegionMap::new();
|
||||
free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
|
||||
.caller_bounds);
|
||||
infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
|
||||
infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
|
||||
|
||||
CoerceUnsizedInfo {
|
||||
custom_kind: kind
|
||||
|
@ -1,4 +1,4 @@
|
||||
s// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user