From f4ea3928aca448788e0d3abc05d7ece832278f80 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Thu, 14 May 2015 23:40:16 +1200 Subject: [PATCH 1/7] Introduce callback to resolver Sets a flag to pass through the rest of the walker. --- src/librustc_resolve/lib.rs | 108 ++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 16 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fa9c7a2038c80..b6e9619129ba2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -397,7 +397,7 @@ enum PatternBindingMode { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -enum Namespace { +pub enum Namespace { TypeNS, ValueNS } @@ -445,18 +445,38 @@ enum NameDefinition { impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeItem(item), &mut self.resolved) { + return; + } + } self.resolve_item(item); } fn visit_arm(&mut self, arm: &Arm) { self.resolve_arm(arm); } fn visit_block(&mut self, block: &Block) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeBlock(block), &mut self.resolved) { + return; + } + } self.resolve_block(block); } fn visit_expr(&mut self, expr: &Expr) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeExpr(expr), &mut self.resolved) { + return; + } + } self.resolve_expr(expr); } fn visit_local(&mut self, local: &Local) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeLocal(&*local.pat), &mut self.resolved) { + return; + } + } self.resolve_local(local); } fn visit_ty(&mut self, ty: &Ty) { @@ -475,6 +495,11 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { visit::walk_poly_trait_ref(self, tref, m); } fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeVariant(variant), &mut self.resolved) { + return; + } + } if let Some(ref dis_expr) = variant.node.disr_expr { // resolve the discriminator expr as a constant self.with_constant_rib(|this| { @@ -498,6 +523,11 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { } } fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) { + if let Some(ref callback) = self.callback { + if callback(ast_map::Node::NodeForeignItem(foreign_item), &mut self.resolved) { + return; + } + } let type_parameters = match foreign_item.node { ForeignItemFn(_, ref generics) => { HasTypeParameters(generics, FnSpace, ItemRibKind) @@ -1110,6 +1140,13 @@ pub struct Resolver<'a, 'tcx:'a> { used_imports: HashSet<(NodeId, Namespace)>, used_crates: HashSet, + + // Callback function for intercepting walks + callback: Option bool>>, + // The intention is that the callback modifies this flag. + // Once set, the resolver falls out of the walk, preserving the ribs. + resolved: bool, + } #[derive(PartialEq)] @@ -1171,6 +1208,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { emit_errors: true, make_glob_map: make_glob_map == MakeGlobMap::Yes, glob_map: HashMap::new(), + + callback: None, + resolved: false, + } } @@ -2207,7 +2248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { f(self); match type_parameters { - HasTypeParameters(..) => { self.type_ribs.pop(); } + HasTypeParameters(..) => { if !self.resolved { self.type_ribs.pop(); } } NoTypeParameters => { } } } @@ -2217,7 +2258,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { self.label_ribs.push(Rib::new(NormalRibKind)); f(self); - self.label_ribs.pop(); + if !self.resolved { + self.label_ribs.pop(); + } } fn with_constant_rib(&mut self, f: F) where @@ -2226,8 +2269,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.value_ribs.push(Rib::new(ConstantItemRibKind)); self.type_ribs.push(Rib::new(ConstantItemRibKind)); f(self); - self.type_ribs.pop(); - self.value_ribs.pop(); + if !self.resolved { + self.type_ribs.pop(); + self.value_ribs.pop(); + } } fn resolve_function(&mut self, @@ -2258,8 +2303,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving function) leaving function"); - self.label_ribs.pop(); - self.value_ribs.pop(); + if !self.resolved { + self.label_ribs.pop(); + self.value_ribs.pop(); + } } fn resolve_trait_reference(&mut self, @@ -2362,7 +2409,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self_type_rib.bindings.insert(name, DlDef(self_def)); self.type_ribs.push(self_type_rib); f(self); - self.type_ribs.pop(); + if !self.resolved { + self.type_ribs.pop(); + } } fn resolve_implementation(&mut self, @@ -2531,7 +2580,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_expr_opt(self, &arm.guard); self.visit_expr(&*arm.body); - self.value_ribs.pop(); + if !self.resolved { + self.value_ribs.pop(); + } } fn resolve_block(&mut self, block: &Block) { @@ -2575,7 +2626,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Move back up. self.current_module = orig_module; - self.value_ribs.pop(); + if !self.resolved { + self.value_ribs.pop(); + } debug!("(resolving block) leaving block"); } @@ -3017,12 +3070,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// doesn't skip straight to the containing module. /// Skips `path_depth` trailing segments, which is also reflected in the /// returned value. See `middle::def::PathResolution` for more info. - fn resolve_path(&mut self, - id: NodeId, - path: &Path, - path_depth: usize, - namespace: Namespace, - check_ribs: bool) -> Option { + pub fn resolve_path(&mut self, + id: NodeId, + path: &Path, + path_depth: usize, + namespace: Namespace, + check_ribs: bool) -> Option { let span = path.span; let segments = &path.segments[..path.segments.len()-path_depth]; @@ -3991,4 +4044,27 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, } } +pub fn create_resolver<'a, 'tcx>(session: &'a Session, + ast_map: &'a ast_map::Map<'tcx>, + _: &LanguageItems, + krate: &'a Crate, + make_glob_map: MakeGlobMap, + callback: Option bool>>) + -> Resolver<'a, 'tcx> { + let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map); + + resolver.callback = callback; + + build_reduced_graph::build_reduced_graph(&mut resolver, krate); + session.abort_if_errors(); + + resolve_imports::resolve_imports(&mut resolver); + session.abort_if_errors(); + + record_exports::record(&mut resolver); + session.abort_if_errors(); + + resolver +} + __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } From ff6dd5c24b0da35d5ad1e0e20082f3d62b74b190 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Sat, 6 Jun 2015 15:19:15 +1200 Subject: [PATCH 2/7] Avoid change to current module on escape from callback --- src/librustc_resolve/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b6e9619129ba2..d89fd635c7ac7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2624,9 +2624,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_block(self, block); // Move back up. - self.current_module = orig_module; - if !self.resolved { + self.current_module = orig_module; self.value_ribs.pop(); } debug!("(resolving block) leaving block"); From 251696ed0da7c2c829de0b61f1ea930b815cfbd2 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Fri, 3 Jul 2015 00:01:49 +1200 Subject: [PATCH 3/7] Remove unused language items --- src/librustc_resolve/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d89fd635c7ac7..b39703049ec77 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4045,7 +4045,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, pub fn create_resolver<'a, 'tcx>(session: &'a Session, ast_map: &'a ast_map::Map<'tcx>, - _: &LanguageItems, krate: &'a Crate, make_glob_map: MakeGlobMap, callback: Option bool>>) From 8b98256f64362cc524952c0641f4e23c27937db1 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Mon, 27 Jul 2015 18:40:34 +1200 Subject: [PATCH 4/7] Remove some duplicated code with new create_resolver --- src/librustc_resolve/lib.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b39703049ec77..37bf571e0bb89 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4013,16 +4013,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, make_glob_map: MakeGlobMap) -> CrateMap { let krate = ast_map.krate(); - let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map); - - build_reduced_graph::build_reduced_graph(&mut resolver, krate); - session.abort_if_errors(); - - resolve_imports::resolve_imports(&mut resolver); - session.abort_if_errors(); - - record_exports::record(&mut resolver); - session.abort_if_errors(); + let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None); resolver.resolve_crate(krate); session.abort_if_errors(); From ed9f8f83c90e995ad41f8c3c26f81d34900ec631 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Mon, 3 Aug 2015 20:05:57 +1200 Subject: [PATCH 5/7] Expose more of the save analysis module --- src/librustc_trans/save/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 8d3be7c8c6070..083461cdc4793 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -28,8 +28,8 @@ use syntax::print::pprust::ty_to_string; use self::span_utils::SpanUtils; -mod span_utils; -mod recorder; +pub mod span_utils; +pub mod recorder; mod dump_csv; @@ -661,7 +661,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } #[inline] - fn enclosing_scope(&self, id: NodeId) -> NodeId { + pub fn enclosing_scope(&self, id: NodeId) -> NodeId { self.tcx.map.get_enclosing_scope(id).unwrap_or(0) } } From fdba872944675a2c2aa146ab3caadbad14452e97 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Sun, 9 Aug 2015 21:09:55 +1200 Subject: [PATCH 6/7] Add a proper comment for create_resolver --- src/librustc_resolve/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 37bf571e0bb89..d044202c3ef50 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4034,6 +4034,14 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, } } +/// Builds a name resolution walker to be used within this module, +/// or used externally, with an optional callback function. +/// +/// The callback takes a &mut bool which allows callbacks to end a +/// walk when set to true, passing through the rest of the walk, while +/// preserving the ribs + current module. This allows resolve_path +/// calls to be made with the correct scope info. The node in the +/// callback corresponds to the current node in the walk. pub fn create_resolver<'a, 'tcx>(session: &'a Session, ast_map: &'a ast_map::Map<'tcx>, krate: &'a Crate, From fc9ecae4442ba39ed1474a129d10bd37c7fdab00 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Mon, 10 Aug 2015 18:39:24 +1200 Subject: [PATCH 7/7] Modify the callback to be run from a macro --- src/librustc_resolve/lib.rs | 47 ++++++++++++++----------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d044202c3ef50..9a854d3c91d9f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -108,6 +108,17 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; +// Perform the callback, not walking deeper if the return is true +macro_rules! execute_callback { + ($node: expr, $walker: expr) => ( + if let Some(ref callback) = $walker.callback { + if callback($node, &mut $walker.resolved) { + return; + } + } + ) +} + pub enum ResolutionError<'a> { /// error E0401: can't use type parameters from outer function TypeParametersFromOuterFunction, @@ -445,38 +456,22 @@ enum NameDefinition { impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeItem(item), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeItem(item), self); self.resolve_item(item); } fn visit_arm(&mut self, arm: &Arm) { self.resolve_arm(arm); } fn visit_block(&mut self, block: &Block) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeBlock(block), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeBlock(block), self); self.resolve_block(block); } fn visit_expr(&mut self, expr: &Expr) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeExpr(expr), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeExpr(expr), self); self.resolve_expr(expr); } fn visit_local(&mut self, local: &Local) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeLocal(&*local.pat), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeLocal(&*local.pat), self); self.resolve_local(local); } fn visit_ty(&mut self, ty: &Ty) { @@ -495,11 +490,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { visit::walk_poly_trait_ref(self, tref, m); } fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeVariant(variant), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeVariant(variant), self); if let Some(ref dis_expr) = variant.node.disr_expr { // resolve the discriminator expr as a constant self.with_constant_rib(|this| { @@ -523,11 +514,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { } } fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) { - if let Some(ref callback) = self.callback { - if callback(ast_map::Node::NodeForeignItem(foreign_item), &mut self.resolved) { - return; - } - } + execute_callback!(ast_map::Node::NodeForeignItem(foreign_item), self); let type_parameters = match foreign_item.node { ForeignItemFn(_, ref generics) => { HasTypeParameters(generics, FnSpace, ItemRibKind)