librustc: Change the ID visitor to use traits instead of garbage-collected functions.
This commit is contained in:
parent
37c32e2495
commit
6ecbd75843
|
@ -24,6 +24,7 @@ use middle;
|
|||
use util::ppaux::ty_to_str;
|
||||
|
||||
use std::at_vec;
|
||||
use std::libc;
|
||||
use extra::ebml::reader;
|
||||
use extra::ebml;
|
||||
use extra::serialize;
|
||||
|
@ -849,6 +850,26 @@ impl write_tag_and_id for writer::Encoder {
|
|||
}
|
||||
}
|
||||
|
||||
struct SideTableEncodingIdVisitor {
|
||||
ecx_ptr: *libc::c_void,
|
||||
new_ebml_w: writer::Encoder,
|
||||
maps: Maps,
|
||||
}
|
||||
|
||||
impl ast_util::IdVisitingOperation for SideTableEncodingIdVisitor {
|
||||
fn visit_id(&self, id: ast::NodeId) {
|
||||
// Note: this will cause a copy of ebml_w, which is bad as
|
||||
// it is mutable. But I believe it's harmless since we generate
|
||||
// balanced EBML.
|
||||
let mut new_ebml_w = self.new_ebml_w.clone();
|
||||
// See above
|
||||
let ecx: &e::EncodeContext = unsafe {
|
||||
cast::transmute(self.ecx_ptr)
|
||||
};
|
||||
encode_side_tables_for_id(ecx, self.maps, &mut new_ebml_w, id)
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
|
||||
maps: Maps,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
|
@ -856,22 +877,16 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
|
|||
ebml_w.start_tag(c::tag_table as uint);
|
||||
let new_ebml_w = (*ebml_w).clone();
|
||||
|
||||
// Because the ast visitor uses @fn, I can't pass in
|
||||
// ecx directly, but /I/ know that it'll be fine since
|
||||
// the lifetime is tied to the CrateContext that
|
||||
// lives this entire section.
|
||||
let ecx_ptr : *() = unsafe { cast::transmute(ecx) };
|
||||
ast_util::visit_ids_for_inlined_item(
|
||||
ii,
|
||||
|id: ast::NodeId| {
|
||||
// Note: this will cause a copy of ebml_w, which is bad as
|
||||
// it is mutable. But I believe it's harmless since we generate
|
||||
// balanced EBML.
|
||||
let mut new_ebml_w = new_ebml_w.clone();
|
||||
// See above
|
||||
let ecx : &e::EncodeContext = unsafe { cast::transmute(ecx_ptr) };
|
||||
encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
|
||||
});
|
||||
// Because the ast visitor uses @IdVisitingOperation, I can't pass in
|
||||
// ecx directly, but /I/ know that it'll be fine since the lifetime is
|
||||
// tied to the CrateContext that lives throughout this entire section.
|
||||
ast_util::visit_ids_for_inlined_item(ii, @SideTableEncodingIdVisitor {
|
||||
ecx_ptr: unsafe {
|
||||
cast::transmute(ecx)
|
||||
},
|
||||
new_ebml_w: new_ebml_w,
|
||||
maps: maps,
|
||||
} as @ast_util::IdVisitingOperation);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
|
|
|
@ -1228,17 +1228,27 @@ fn lint_unused_mut() -> @mut OuterLint {
|
|||
@mut UnusedMutLintVisitor{ stopping_on_items: false } as @mut OuterLint
|
||||
}
|
||||
|
||||
fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
|
||||
ast_util::id_visitor(|id| {
|
||||
match cx.tcx.sess.lints.pop(&id) {
|
||||
None => {},
|
||||
struct LintReportingIdVisitor {
|
||||
cx: @mut Context,
|
||||
}
|
||||
|
||||
impl ast_util::IdVisitingOperation for LintReportingIdVisitor {
|
||||
fn visit_id(&self, id: ast::NodeId) {
|
||||
match self.cx.tcx.sess.lints.pop(&id) {
|
||||
None => {}
|
||||
Some(l) => {
|
||||
for (lint, span, msg) in l.move_iter() {
|
||||
cx.span_lint(lint, span, msg)
|
||||
self.cx.span_lint(lint, span, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
|
||||
ast_util::id_visitor(@LintReportingIdVisitor {
|
||||
cx: cx,
|
||||
} as @ast_util::IdVisitingOperation, false)
|
||||
}
|
||||
|
||||
struct UnnecessaryAllocationLintVisitor { stopping_on_items: bool }
|
||||
|
|
|
@ -299,7 +299,7 @@ struct RustcEmitter {
|
|||
|
||||
impl diagnostic::Emitter for RustcEmitter {
|
||||
fn emit(&self,
|
||||
cmsp: Option<(@codemap::CodeMap, codemap::span)>,
|
||||
cmsp: Option<(@codemap::CodeMap, codemap::Span)>,
|
||||
msg: &str,
|
||||
lvl: diagnostic::level) {
|
||||
if lvl == diagnostic::fatal {
|
||||
|
|
|
@ -397,18 +397,22 @@ impl id_range {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool)
|
||||
pub fn id_visitor(operation: @IdVisitingOperation, pass_through_items: bool)
|
||||
-> @mut Visitor<()> {
|
||||
let visitor = @mut IdVisitor {
|
||||
visit_callback: vfn,
|
||||
operation: operation,
|
||||
pass_through_items: pass_through_items,
|
||||
visited_outermost: false,
|
||||
};
|
||||
visitor as @mut Visitor<()>
|
||||
}
|
||||
|
||||
pub trait IdVisitingOperation {
|
||||
fn visit_id(&self, node_id: NodeId);
|
||||
}
|
||||
|
||||
pub struct IdVisitor {
|
||||
visit_callback: @fn(NodeId),
|
||||
operation: @IdVisitingOperation,
|
||||
pass_through_items: bool,
|
||||
visited_outermost: bool,
|
||||
}
|
||||
|
@ -416,10 +420,10 @@ pub struct IdVisitor {
|
|||
impl IdVisitor {
|
||||
fn visit_generics_helper(&self, generics: &Generics) {
|
||||
for type_parameter in generics.ty_params.iter() {
|
||||
(self.visit_callback)(type_parameter.id)
|
||||
self.operation.visit_id(type_parameter.id)
|
||||
}
|
||||
for lifetime in generics.lifetimes.iter() {
|
||||
(self.visit_callback)(lifetime.id)
|
||||
self.operation.visit_id(lifetime.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -430,26 +434,26 @@ impl Visitor<()> for IdVisitor {
|
|||
_: Span,
|
||||
node_id: NodeId,
|
||||
env: ()) {
|
||||
(self.visit_callback)(node_id);
|
||||
self.operation.visit_id(node_id);
|
||||
visit::walk_mod(self, module, env)
|
||||
}
|
||||
|
||||
fn visit_view_item(&mut self, view_item: &view_item, env: ()) {
|
||||
match view_item.node {
|
||||
view_item_extern_mod(_, _, _, node_id) => {
|
||||
(self.visit_callback)(node_id)
|
||||
self.operation.visit_id(node_id)
|
||||
}
|
||||
view_item_use(ref view_paths) => {
|
||||
for view_path in view_paths.iter() {
|
||||
match view_path.node {
|
||||
view_path_simple(_, _, node_id) |
|
||||
view_path_glob(_, node_id) => {
|
||||
(self.visit_callback)(node_id)
|
||||
self.operation.visit_id(node_id)
|
||||
}
|
||||
view_path_list(_, ref paths, node_id) => {
|
||||
(self.visit_callback)(node_id);
|
||||
self.operation.visit_id(node_id);
|
||||
for path in paths.iter() {
|
||||
(self.visit_callback)(path.node.id)
|
||||
self.operation.visit_id(path.node.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +464,7 @@ impl Visitor<()> for IdVisitor {
|
|||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: @foreign_item, env: ()) {
|
||||
(self.visit_callback)(foreign_item.id);
|
||||
self.operation.visit_id(foreign_item.id);
|
||||
visit::walk_foreign_item(self, foreign_item, env)
|
||||
}
|
||||
|
||||
|
@ -473,11 +477,11 @@ impl Visitor<()> for IdVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
(self.visit_callback)(item.id);
|
||||
self.operation.visit_id(item.id);
|
||||
match item.node {
|
||||
item_enum(ref enum_definition, _) => {
|
||||
for variant in enum_definition.variants.iter() {
|
||||
(self.visit_callback)(variant.node.id)
|
||||
self.operation.visit_id(variant.node.id)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -489,22 +493,22 @@ impl Visitor<()> for IdVisitor {
|
|||
}
|
||||
|
||||
fn visit_local(&mut self, local: @Local, env: ()) {
|
||||
(self.visit_callback)(local.id);
|
||||
self.operation.visit_id(local.id);
|
||||
visit::walk_local(self, local, env)
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &Block, env: ()) {
|
||||
(self.visit_callback)(block.id);
|
||||
self.operation.visit_id(block.id);
|
||||
visit::walk_block(self, block, env)
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, statement: @Stmt, env: ()) {
|
||||
(self.visit_callback)(ast_util::stmt_id(statement));
|
||||
self.operation.visit_id(ast_util::stmt_id(statement));
|
||||
visit::walk_stmt(self, statement, env)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pattern: @Pat, env: ()) {
|
||||
(self.visit_callback)(pattern.id);
|
||||
self.operation.visit_id(pattern.id);
|
||||
visit::walk_pat(self, pattern, env)
|
||||
}
|
||||
|
||||
|
@ -513,17 +517,17 @@ impl Visitor<()> for IdVisitor {
|
|||
{
|
||||
let optional_callee_id = expression.get_callee_id();
|
||||
for callee_id in optional_callee_id.iter() {
|
||||
(self.visit_callback)(*callee_id)
|
||||
self.operation.visit_id(*callee_id)
|
||||
}
|
||||
}
|
||||
(self.visit_callback)(expression.id);
|
||||
self.operation.visit_id(expression.id);
|
||||
visit::walk_expr(self, expression, env)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, typ: &Ty, env: ()) {
|
||||
(self.visit_callback)(typ.id);
|
||||
self.operation.visit_id(typ.id);
|
||||
match typ.node {
|
||||
ty_path(_, _, id) => (self.visit_callback)(id),
|
||||
ty_path(_, _, id) => self.operation.visit_id(id),
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, typ, env)
|
||||
|
@ -549,21 +553,21 @@ impl Visitor<()> for IdVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
(self.visit_callback)(node_id);
|
||||
self.operation.visit_id(node_id);
|
||||
|
||||
match *function_kind {
|
||||
visit::fk_item_fn(_, generics, _, _) => {
|
||||
self.visit_generics_helper(generics)
|
||||
}
|
||||
visit::fk_method(_, generics, method) => {
|
||||
(self.visit_callback)(method.self_id);
|
||||
self.operation.visit_id(method.self_id);
|
||||
self.visit_generics_helper(generics)
|
||||
}
|
||||
visit::fk_anon(_) | visit::fk_fn_block => {}
|
||||
}
|
||||
|
||||
for argument in function_declaration.inputs.iter() {
|
||||
(self.visit_callback)(argument.id)
|
||||
self.operation.visit_id(argument.id)
|
||||
}
|
||||
|
||||
visit::walk_fn(self,
|
||||
|
@ -583,25 +587,36 @@ impl Visitor<()> for IdVisitor {
|
|||
}
|
||||
|
||||
fn visit_struct_field(&mut self, struct_field: @struct_field, env: ()) {
|
||||
(self.visit_callback)(struct_field.node.id);
|
||||
self.operation.visit_id(struct_field.node.id);
|
||||
visit::walk_struct_field(self, struct_field, env)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) {
|
||||
pub fn visit_ids_for_inlined_item(item: &inlined_item,
|
||||
operation: @IdVisitingOperation) {
|
||||
let mut id_visitor = IdVisitor {
|
||||
visit_callback: vfn,
|
||||
operation: operation,
|
||||
pass_through_items: true,
|
||||
visited_outermost: false,
|
||||
};
|
||||
item.accept((), &mut id_visitor);
|
||||
}
|
||||
|
||||
pub fn compute_id_range(visit_ids_fn: &fn(@fn(NodeId))) -> id_range {
|
||||
let result = @mut id_range::max();
|
||||
do visit_ids_fn |id| {
|
||||
result.add(id);
|
||||
struct IdRangeComputingVisitor {
|
||||
result: @mut id_range,
|
||||
}
|
||||
|
||||
impl IdVisitingOperation for IdRangeComputingVisitor {
|
||||
fn visit_id(&self, id: NodeId) {
|
||||
self.result.add(id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_id_range(visit_ids_fn: &fn(@IdVisitingOperation)) -> id_range {
|
||||
let result = @mut id_range::max();
|
||||
visit_ids_fn(@IdRangeComputingVisitor {
|
||||
result: result,
|
||||
} as @IdVisitingOperation);
|
||||
*result
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue