From 69e822dcb3af7bceac1b1a3af4eeb2d67c1b12ca Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 13 Aug 2013 13:53:13 +0200 Subject: [PATCH] port reachable.rs from oldvisit to trait. --- src/librustc/middle/reachable.rs | 207 ++++++++++++++++++------------- 1 file changed, 118 insertions(+), 89 deletions(-) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 33a8960baee5..b6a4ac49391a 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -24,8 +24,8 @@ use syntax::ast_map; use syntax::ast_util::def_id_of_def; use syntax::attr; use syntax::parse::token; -use syntax::oldvisit::Visitor; -use syntax::oldvisit; +use syntax::visit::Visitor; +use syntax::visit; // Returns true if the given set of attributes contains the `#[inline]` // attribute. @@ -94,40 +94,29 @@ struct ReachableContext { worklist: @mut ~[NodeId], } -impl ReachableContext { - // Creates a new reachability computation context. - fn new(tcx: ty::ctxt, method_map: typeck::method_map) - -> ReachableContext { - ReachableContext { - tcx: tcx, - method_map: method_map, - reachable_symbols: @mut HashSet::new(), - worklist: @mut ~[], - } - } +struct ReachableVisitor { + reachable_symbols: @mut HashSet, + worklist: @mut ~[NodeId], +} + +impl Visitor for ReachableVisitor { + + fn visit_item(&mut self, item:@item, privacy_context:PrivacyContext) { - // Step 1: Mark all public symbols, and add all public symbols that might - // be inlined to a worklist. - fn mark_public_symbols(&self, crate: @Crate) { - let reachable_symbols = self.reachable_symbols; - let worklist = self.worklist; - let visitor = oldvisit::mk_vt(@Visitor { - visit_item: |item, (privacy_context, visitor): - (PrivacyContext, oldvisit::vt)| { match item.node { item_fn(*) => { if privacy_context == PublicContext { - reachable_symbols.insert(item.id); + self.reachable_symbols.insert(item.id); } if item_might_be_inlined(item) { - worklist.push(item.id) + self.worklist.push(item.id) } } item_struct(ref struct_def, _) => { match struct_def.ctor_id { Some(ctor_id) if privacy_context == PublicContext => { - reachable_symbols.insert(ctor_id); + self.reachable_symbols.insert(ctor_id); } Some(_) | None => {} } @@ -135,7 +124,7 @@ impl ReachableContext { item_enum(ref enum_def, _) => { if privacy_context == PublicContext { for variant in enum_def.variants.iter() { - reachable_symbols.insert(variant.node.id); + self.reachable_symbols.insert(variant.node.id); } } } @@ -155,7 +144,7 @@ impl ReachableContext { // Mark all public methods as reachable. for &method in methods.iter() { if should_be_considered_public(method) { - reachable_symbols.insert(method.id); + self.reachable_symbols.insert(method.id); } } @@ -164,7 +153,7 @@ impl ReachableContext { // symbols to the worklist. for &method in methods.iter() { if should_be_considered_public(method) { - worklist.push(method.id) + self.worklist.push(method.id) } } } else { @@ -176,7 +165,7 @@ impl ReachableContext { if generics_require_inlining(generics) || attributes_specify_inlining(*attrs) || should_be_considered_public(*method) { - worklist.push(method.id) + self.worklist.push(method.id) } } } @@ -187,8 +176,8 @@ impl ReachableContext { for trait_method in trait_methods.iter() { match *trait_method { provided(method) => { - reachable_symbols.insert(method.id); - worklist.push(method.id) + self.reachable_symbols.insert(method.id); + self.worklist.push(method.id) } required(_) => {} } @@ -199,15 +188,97 @@ impl ReachableContext { } if item.vis == public && privacy_context == PublicContext { - oldvisit::visit_item(item, (PublicContext, visitor)) + visit::walk_item(self, item, PublicContext) } else { - oldvisit::visit_item(item, (PrivateContext, visitor)) + visit::walk_item(self, item, PrivateContext) } - }, - .. *oldvisit::default_visitor() - }); + } - oldvisit::visit_crate(crate, (PublicContext, visitor)) +} + +struct MarkSymbolVisitor { + worklist: @mut ~[NodeId], + method_map: typeck::method_map, + tcx: ty::ctxt, + reachable_symbols: @mut HashSet, +} + +impl Visitor<()> for MarkSymbolVisitor { + + fn visit_expr(&mut self, expr:@expr, _:()) { + + match expr.node { + expr_path(_) => { + let def = match self.tcx.def_map.find(&expr.id) { + Some(&def) => def, + None => { + self.tcx.sess.span_bug(expr.span, + "def ID not in def map?!") + } + }; + + let def_id = def_id_of_def(def); + if ReachableContext:: + def_id_represents_local_inlined_item(self.tcx, + def_id) { + self.worklist.push(def_id.node) + } + self.reachable_symbols.insert(def_id.node); + } + expr_method_call(*) => { + match self.method_map.find(&expr.id) { + Some(&typeck::method_map_entry { + origin: typeck::method_static(def_id), + _ + }) => { + if ReachableContext:: + def_id_represents_local_inlined_item( + self.tcx, + def_id) { + self.worklist.push(def_id.node) + } + self.reachable_symbols.insert(def_id.node); + } + Some(_) => {} + None => { + self.tcx.sess.span_bug(expr.span, + "method call expression \ + not in method map?!") + } + } + } + _ => {} + } + + visit::walk_expr(self, expr, ()) + } +} + +impl ReachableContext { + // Creates a new reachability computation context. + fn new(tcx: ty::ctxt, method_map: typeck::method_map) + -> ReachableContext { + ReachableContext { + tcx: tcx, + method_map: method_map, + reachable_symbols: @mut HashSet::new(), + worklist: @mut ~[], + } + } + + // Step 1: Mark all public symbols, and add all public symbols that might + // be inlined to a worklist. + fn mark_public_symbols(&self, crate: @Crate) { + let reachable_symbols = self.reachable_symbols; + let worklist = self.worklist; + + let mut visitor = ReachableVisitor { + reachable_symbols: reachable_symbols, + worklist: worklist, + }; + + + visit::walk_crate(&mut visitor, crate, PublicContext); } // Returns true if the given def ID represents a local item that is @@ -269,63 +340,21 @@ impl ReachableContext { } // Helper function to set up a visitor for `propagate()` below. - fn init_visitor(&self) -> oldvisit::vt<()> { + fn init_visitor(&self) -> MarkSymbolVisitor { let (worklist, method_map) = (self.worklist, self.method_map); let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols); - oldvisit::mk_vt(@oldvisit::Visitor { - visit_expr: |expr, (_, visitor)| { - match expr.node { - expr_path(_) => { - let def = match tcx.def_map.find(&expr.id) { - Some(&def) => def, - None => { - tcx.sess.span_bug(expr.span, - "def ID not in def map?!") - } - }; - let def_id = def_id_of_def(def); - if ReachableContext:: - def_id_represents_local_inlined_item(tcx, - def_id) { - worklist.push(def_id.node) - } - reachable_symbols.insert(def_id.node); - } - expr_method_call(*) => { - match method_map.find(&expr.id) { - Some(&typeck::method_map_entry { - origin: typeck::method_static(def_id), - _ - }) => { - if ReachableContext:: - def_id_represents_local_inlined_item( - tcx, - def_id) { - worklist.push(def_id.node) - } - reachable_symbols.insert(def_id.node); - } - Some(_) => {} - None => { - tcx.sess.span_bug(expr.span, - "method call expression \ - not in method map?!") - } - } - } - _ => {} - } - - oldvisit::visit_expr(expr, ((), visitor)) - }, - ..*oldvisit::default_visitor() - }) + MarkSymbolVisitor { + worklist: worklist, + method_map: method_map, + tcx: tcx, + reachable_symbols: reachable_symbols, + } } // Step 2: Mark all symbols that the symbols on the worklist touch. fn propagate(&self) { - let visitor = self.init_visitor(); + let mut visitor = self.init_visitor(); let mut scanned = HashSet::new(); while self.worklist.len() > 0 { let search_item = self.worklist.pop(); @@ -342,7 +371,7 @@ impl ReachableContext { Some(&ast_map::node_item(item, _)) => { match item.node { item_fn(_, _, _, _, ref search_block) => { - oldvisit::visit_block(search_block, ((), visitor)) + visit::walk_block(&mut visitor, search_block, ()) } _ => { self.tcx.sess.span_bug(item.span, @@ -359,12 +388,12 @@ impl ReachableContext { worklist?!") } provided(ref method) => { - oldvisit::visit_block(&method.body, ((), visitor)) + visit::walk_block(&mut visitor, &method.body, ()) } } } Some(&ast_map::node_method(ref method, _, _)) => { - oldvisit::visit_block(&method.body, ((), visitor)) + visit::walk_block(&mut visitor, &method.body, ()) } Some(_) => { let ident_interner = token::get_ident_interner();