From ec23e3f4b8307d14443ddf9a70f2acb5c519c486 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 10 Apr 2017 23:51:35 -0700 Subject: [PATCH] Convert fn_id to outermost in region_maps --- src/librustc/hir/map/mod.rs | 12 ++++++++++++ src/librustc/middle/region.rs | 27 +++++++++++++++++++++------ src/librustc/ty/context.rs | 15 +++++++++++++-- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 48b8a819fff03..cae5c5011ce7e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -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), diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 19e6aafd6b222..81e99e52ffbdd 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -348,7 +348,7 @@ struct RegionResolutionVisitor<'hir: 'a, 'a> { /// destructor's execution. terminating_scopes: NodeSet, - target_fn_id: DefId, + target_fn_node_id: NodeId, found_target_fn: bool, } @@ -1142,11 +1142,10 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, body_id: hir::BodyId, sp: Span, id: ast::NodeId) { - visitor.cx.parent = visitor.new_code_extent( CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }); - if body_id == visitor.target_fn_id { + if id == visitor.target_fn_node_id { // We've found the top level `fn`. Store it and its children in the `RegionMaps` visitor.found_target_fn = true; } @@ -1270,8 +1269,23 @@ impl<'hir, 'a> Visitor<'hir> for RegionResolutionVisitor<'hir, 'a> { } } -pub fn resolve_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc { - ty::queries::region_resolve_fn::get(tcx, DUMMY_SP, LOCAL_CRATE) +pub fn resolve_crate<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + + struct CrateResolutionVisitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>); + + impl<'a, 'hir: 'a> Visitor<'hir> for CrateResolutionVisitor<'a, 'hir> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { + NestedVisitorMap::OnlyBodies(&self.0.hir) + } + fn visit_fn(&mut self, _fk: FnKind<'hir>, _fd: &'hir FnDecl, + _b: hir::BodyId, _s: Span, fn_id: NodeId) + { + let fn_def_id = self.0.hir.local_def_id(fn_id); + ty::queries::region_resolve_fn::get(self.0, DUMMY_SP, fn_def_id); + } + } + + tcx.hir.krate().visit_all_item_likes(&mut CrateResolutionVisitor(tcx).as_deep_visitor()); } fn region_resolve_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId) @@ -1308,7 +1322,8 @@ fn region_resolve_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_id: DefId) var_parent: ROOT_CODE_EXTENT }, terminating_scopes: NodeSet(), - target_fn_id: fn_id, + target_fn_node_id: hir_map.as_local_node_id(fn_id) + .expect("fn DefId should be for LOCAL_CRATE"), found_target_fn: false, }; krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 97cfa9c9de945..a33a788221815 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -663,8 +663,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { local as usize == global as usize } - pub fn region_maps(self) -> Rc { - ty::queries::region_resolve_crate::get(self, DUMMY_SP, LOCAL_CRATE) + pub fn region_maps(self, fn_id: NodeId) -> Rc { + // Find the `NodeId` of the outermost function that wraps the function pointed to by fn_id + let mut outermost_fn_id = fn_id; + let mut outermost_id = fn_id; + loop { + let next_id = self.hir.get_parent(outermost_id); + if outermost_id == next_id { break; } + if self.hir.is_fn(outermost_id) { + outermost_fn_id = outermost_id; + } + } + + ty::queries::region_resolve_fn::get(self, DUMMY_SP, self.hir.local_def_id(outermost_fn_id)) } /// Create a type context and call the closure with a `TyCtxt` reference