Prevent refcount cycles during linting
Shaves off ~600MB of memory while compiling rustc
This commit is contained in:
parent
e6a838d051
commit
ae7df57c5a
@ -299,7 +299,7 @@ struct Context {
|
||||
// Others operate directly on @ast::item structures (or similar). Finally,
|
||||
// others still are added to the Session object via `add_lint`, and these
|
||||
// are all passed with the lint_session visitor.
|
||||
visitors: ~[visit::vt<()>],
|
||||
visitors: ~[visit::vt<@mut Context>],
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@ -416,20 +416,20 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_lint(&mut self, v: visit::vt<()>) {
|
||||
fn add_lint(&mut self, v: visit::vt<@mut Context>) {
|
||||
self.visitors.push(item_stopping_visitor(v));
|
||||
}
|
||||
|
||||
fn process(&self, n: AttributedNode) {
|
||||
fn process(@mut self, n: AttributedNode) {
|
||||
match n {
|
||||
Item(it) => {
|
||||
for self.visitors.each |v| {
|
||||
visit::visit_item(it, (), *v);
|
||||
visit::visit_item(it, self, *v);
|
||||
}
|
||||
}
|
||||
Crate(c) => {
|
||||
for self.visitors.each |v| {
|
||||
visit::visit_crate(c, (), *v);
|
||||
visit::visit_crate(c, self, *v);
|
||||
}
|
||||
}
|
||||
// Can't use visit::visit_method_helper because the
|
||||
@ -439,7 +439,7 @@ impl Context {
|
||||
let fk = visit::fk_method(copy m.ident, &m.generics, m);
|
||||
for self.visitors.each |v| {
|
||||
visit::visit_fn(&fk, &m.decl, &m.body, m.span, m.id,
|
||||
(), *v);
|
||||
self, *v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,9 +499,9 @@ fn ty_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
|
||||
visit::mk_vt(@visit::Visitor {visit_ty: |_t, _e, _v| { },.. **v})
|
||||
}
|
||||
|
||||
fn lint_while_true(cx: @mut Context) -> visit::vt<()> {
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: |e: @ast::expr| {
|
||||
fn lint_while_true() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_expr: |e, cx: @mut Context, vt| {
|
||||
match e.node {
|
||||
ast::expr_while(cond, _) => {
|
||||
match cond.node {
|
||||
@ -517,12 +517,13 @@ fn lint_while_true(cx: @mut Context) -> visit::vt<()> {
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
visit::visit_expr(e, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
|
||||
fn lint_type_limits() -> visit::vt<@mut Context> {
|
||||
fn is_valid<T:cmp::Ord>(binop: ast::binop, v: T,
|
||||
min: T, max: T) -> bool {
|
||||
match binop {
|
||||
@ -568,7 +569,7 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_limits(cx: @mut Context, binop: ast::binop, l: &ast::expr,
|
||||
fn check_limits(cx: &Context, binop: ast::binop, l: &ast::expr,
|
||||
r: &ast::expr) -> bool {
|
||||
let (lit, expr, swap) = match (&l.node, &r.node) {
|
||||
(&ast::expr_lit(_), _) => (l, r, true),
|
||||
@ -621,26 +622,26 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let visit_expr: @fn(@ast::expr) = |e| {
|
||||
match e.node {
|
||||
ast::expr_binary(ref binop, @ref l, @ref r) => {
|
||||
if is_comparison(*binop)
|
||||
&& !check_limits(cx, *binop, l, r) {
|
||||
cx.span_lint(type_limits, e.span,
|
||||
"comparison is useless due to type limits");
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_expr: |e, cx: @mut Context, vt| {
|
||||
match e.node {
|
||||
ast::expr_binary(ref binop, @ref l, @ref r) => {
|
||||
if is_comparison(*binop)
|
||||
&& !check_limits(cx, *binop, l, r) {
|
||||
cx.span_lint(type_limits, e.span,
|
||||
"comparison is useless due to type limits");
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
};
|
||||
visit::visit_expr(e, cx, vt);
|
||||
},
|
||||
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: visit_expr,
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn check_item_default_methods(cx: @mut Context, item: @ast::item) {
|
||||
fn check_item_default_methods(cx: &Context, item: @ast::item) {
|
||||
match item.node {
|
||||
ast::item_trait(_, _, ref methods) => {
|
||||
for methods.each |method| {
|
||||
@ -657,9 +658,9 @@ fn check_item_default_methods(cx: @mut Context, item: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_ctypes(cx: @mut Context, it: @ast::item) {
|
||||
fn check_item_ctypes(cx: &Context, it: @ast::item) {
|
||||
|
||||
fn check_foreign_fn(cx: @mut Context, decl: &ast::fn_decl) {
|
||||
fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
|
||||
let tys = vec::map(decl.inputs, |a| a.ty );
|
||||
for vec::each(vec::append_one(tys, decl.output)) |ty| {
|
||||
match ty.node {
|
||||
@ -699,7 +700,7 @@ fn check_item_ctypes(cx: @mut Context, it: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) {
|
||||
fn check_type_for_lint(cx: &Context, lint: lint, span: span, ty: ty::t) {
|
||||
if cx.get_level(lint) == allow { return }
|
||||
|
||||
let mut n_box = 0;
|
||||
@ -726,13 +727,13 @@ fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_type(cx: @mut Context, span: span, ty: ty::t) {
|
||||
fn check_type(cx: &Context, span: span, ty: ty::t) {
|
||||
for [managed_heap_memory, owned_heap_memory, heap_memory].each |lint| {
|
||||
check_type_for_lint(cx, *lint, span, ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_heap(cx: @mut Context, it: @ast::item) {
|
||||
fn check_item_heap(cx: &Context, it: @ast::item) {
|
||||
match it.node {
|
||||
ast::item_fn(*) |
|
||||
ast::item_ty(*) |
|
||||
@ -756,19 +757,20 @@ fn check_item_heap(cx: @mut Context, it: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_heap(cx: @mut Context) -> visit::vt<()> {
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: |e| {
|
||||
fn lint_heap() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_expr: |e, cx: @mut Context, vt| {
|
||||
let ty = ty::expr_ty(cx.tcx, e);
|
||||
check_type(cx, e.span, ty);
|
||||
visit::visit_expr(e, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_path_statement(cx: @mut Context) -> visit::vt<()> {
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_stmt: |s| {
|
||||
fn lint_path_statement() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_stmt: |s, cx: @mut Context, vt| {
|
||||
match s.node {
|
||||
ast::stmt_semi(
|
||||
@ast::expr { node: ast::expr_path(_), _ },
|
||||
@ -779,12 +781,13 @@ fn lint_path_statement(cx: @mut Context) -> visit::vt<()> {
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
visit::visit_stmt(s, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
|
||||
fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) {
|
||||
fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool {
|
||||
let ident = cx.sess.str_of(ident);
|
||||
assert!(!ident.is_empty());
|
||||
@ -808,7 +811,7 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_case(cx: @mut Context, ident: ast::ident, span: span) {
|
||||
fn check_case(cx: &Context, ident: ast::ident, span: span) {
|
||||
if !is_camel_case(cx.tcx, ident) {
|
||||
cx.span_lint(non_camel_case_types, span,
|
||||
"type, variant, or trait should have \
|
||||
@ -831,27 +834,26 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_unused_unsafe(cx: @mut Context) -> visit::vt<()> {
|
||||
let visit_expr: @fn(@ast::expr) = |e| {
|
||||
match e.node {
|
||||
ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
|
||||
if !cx.tcx.used_unsafe.contains(&blk.node.id) {
|
||||
cx.span_lint(unused_unsafe, blk.span,
|
||||
"unnecessary `unsafe` block");
|
||||
fn lint_unused_unsafe() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_expr: |e, cx: @mut Context, vt| {
|
||||
match e.node {
|
||||
ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
|
||||
if !cx.tcx.used_unsafe.contains(&blk.node.id) {
|
||||
cx.span_lint(unused_unsafe, blk.span,
|
||||
"unnecessary `unsafe` block");
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
};
|
||||
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: visit_expr,
|
||||
.. *visit::default_simple_visitor()
|
||||
visit::visit_expr(e, cx, vt);
|
||||
},
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> {
|
||||
let check_pat: @fn(@ast::pat) = |p| {
|
||||
fn lint_unused_mut() -> visit::vt<@mut Context> {
|
||||
fn check_pat(cx: &Context, p: @ast::pat) {
|
||||
let mut used = false;
|
||||
let mut bindings = 0;
|
||||
do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
|
||||
@ -866,37 +868,48 @@ fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> {
|
||||
};
|
||||
cx.span_lint(unused_mut, p.span, msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let visit_fn_decl: @fn(&ast::fn_decl) = |fd| {
|
||||
fn visit_fn_decl(cx: &Context, fd: &ast::fn_decl) {
|
||||
for fd.inputs.each |arg| {
|
||||
if arg.is_mutbl {
|
||||
check_pat(arg.pat);
|
||||
check_pat(cx, arg.pat);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_local: |l| {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_local: |l, cx: @mut Context, vt| {
|
||||
if l.node.is_mutbl {
|
||||
check_pat(l.node.pat);
|
||||
check_pat(cx, l.node.pat);
|
||||
}
|
||||
visit::visit_local(l, cx, vt);
|
||||
},
|
||||
visit_fn: |_, fd, _, _, _| visit_fn_decl(fd),
|
||||
visit_ty_method: |tm| visit_fn_decl(&tm.decl),
|
||||
visit_struct_method: |sm| visit_fn_decl(&sm.decl),
|
||||
visit_trait_method: |tm| {
|
||||
visit_fn: |a, fd, b, c, d, cx, vt| {
|
||||
visit_fn_decl(cx, fd);
|
||||
visit::visit_fn(a, fd, b, c, d, cx, vt);
|
||||
},
|
||||
visit_ty_method: |tm, cx, vt| {
|
||||
visit_fn_decl(cx, &tm.decl);
|
||||
visit::visit_ty_method(tm, cx, vt);
|
||||
},
|
||||
visit_struct_method: |sm, cx, vt| {
|
||||
visit_fn_decl(cx, &sm.decl);
|
||||
visit::visit_struct_method(sm, cx, vt);
|
||||
},
|
||||
visit_trait_method: |tm, cx, vt| {
|
||||
match *tm {
|
||||
ast::required(ref tm) => visit_fn_decl(&tm.decl),
|
||||
ast::provided(m) => visit_fn_decl(&m.decl),
|
||||
ast::required(ref tm) => visit_fn_decl(cx, &tm.decl),
|
||||
ast::provided(m) => visit_fn_decl(cx, &m.decl)
|
||||
}
|
||||
visit::visit_trait_method(tm, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_session(cx: @mut Context) -> visit::vt<()> {
|
||||
ast_util::id_visitor(|id| {
|
||||
fn lint_session() -> visit::vt<@mut Context> {
|
||||
ast_util::id_visitor(|id, cx: @mut Context| {
|
||||
match cx.tcx.sess.lints.pop(&id) {
|
||||
None => {},
|
||||
Some(l) => {
|
||||
@ -908,10 +921,10 @@ fn lint_session(cx: @mut Context) -> visit::vt<()> {
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_unnecessary_allocations(cx: @mut Context) -> visit::vt<()> {
|
||||
fn lint_unnecessary_allocations() -> visit::vt<@mut Context> {
|
||||
// Warn if string and vector literals with sigils are immediately borrowed.
|
||||
// Those can have the sigil removed.
|
||||
fn check(cx: @mut Context, e: @ast::expr) {
|
||||
fn check(cx: &Context, e: @ast::expr) {
|
||||
match e.node {
|
||||
ast::expr_vstore(e2, ast::expr_vstore_uniq) |
|
||||
ast::expr_vstore(e2, ast::expr_vstore_box) => {
|
||||
@ -938,19 +951,18 @@ fn lint_unnecessary_allocations(cx: @mut Context) -> visit::vt<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let visit_expr: @fn(@ast::expr) = |e| {
|
||||
check(cx, e);
|
||||
};
|
||||
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: visit_expr,
|
||||
.. *visit::default_simple_visitor()
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_expr: |e, cx: @mut Context, vt| {
|
||||
check(cx, e);
|
||||
visit::visit_expr(e, cx, vt);
|
||||
},
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_missing_struct_doc(cx: @mut Context) -> visit::vt<()> {
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_struct_field: |field| {
|
||||
fn lint_missing_struct_doc() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_struct_field: |field, cx: @mut Context, vt| {
|
||||
let relevant = match field.node.kind {
|
||||
ast::named_field(_, vis) => vis != ast::private,
|
||||
ast::unnamed_field => false,
|
||||
@ -969,14 +981,16 @@ fn lint_missing_struct_doc(cx: @mut Context) -> visit::vt<()> {
|
||||
for a field.");
|
||||
}
|
||||
}
|
||||
|
||||
visit::visit_struct_field(field, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
fn lint_missing_trait_doc(cx: @mut Context) -> visit::vt<()> {
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_trait_method: |method| {
|
||||
fn lint_missing_trait_doc() -> visit::vt<@mut Context> {
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_trait_method: |method, cx: @mut Context, vt| {
|
||||
let mut has_doc = false;
|
||||
let span = match copy *method {
|
||||
ast::required(m) => {
|
||||
@ -1006,8 +1020,9 @@ fn lint_missing_trait_doc(cx: @mut Context) -> visit::vt<()> {
|
||||
cx.span_lint(missing_trait_doc, span, "missing documentation \
|
||||
for a method.");
|
||||
}
|
||||
visit::visit_trait_method(method, cx, vt);
|
||||
},
|
||||
.. *visit::default_simple_visitor()
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
@ -1031,39 +1046,33 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
}
|
||||
|
||||
// Register each of the lint passes with the context
|
||||
cx.add_lint(lint_while_true(cx));
|
||||
cx.add_lint(lint_path_statement(cx));
|
||||
cx.add_lint(lint_heap(cx));
|
||||
cx.add_lint(lint_type_limits(cx));
|
||||
cx.add_lint(lint_unused_unsafe(cx));
|
||||
cx.add_lint(lint_unused_mut(cx));
|
||||
cx.add_lint(lint_session(cx));
|
||||
cx.add_lint(lint_unnecessary_allocations(cx));
|
||||
cx.add_lint(lint_missing_struct_doc(cx));
|
||||
cx.add_lint(lint_missing_trait_doc(cx));
|
||||
|
||||
// type inference doesn't like this being declared below, we need to tell it
|
||||
// what the type of this first function is...
|
||||
let visit_item:
|
||||
@fn(@ast::item, @mut Context, visit::vt<@mut Context>) =
|
||||
|it, cx, vt| {
|
||||
do cx.with_lint_attrs(it.attrs) {
|
||||
check_item_ctypes(cx, it);
|
||||
check_item_non_camel_case_types(cx, it);
|
||||
check_item_default_methods(cx, it);
|
||||
check_item_heap(cx, it);
|
||||
|
||||
cx.process(Item(it));
|
||||
visit::visit_item(it, cx, vt);
|
||||
}
|
||||
};
|
||||
cx.add_lint(lint_while_true());
|
||||
cx.add_lint(lint_path_statement());
|
||||
cx.add_lint(lint_heap());
|
||||
cx.add_lint(lint_type_limits());
|
||||
cx.add_lint(lint_unused_unsafe());
|
||||
cx.add_lint(lint_unused_mut());
|
||||
cx.add_lint(lint_session());
|
||||
cx.add_lint(lint_unnecessary_allocations());
|
||||
cx.add_lint(lint_missing_struct_doc());
|
||||
cx.add_lint(lint_missing_trait_doc());
|
||||
|
||||
// Actually perform the lint checks (iterating the ast)
|
||||
do cx.with_lint_attrs(crate.node.attrs) {
|
||||
cx.process(Crate(crate));
|
||||
|
||||
visit::visit_crate(crate, cx, visit::mk_vt(@visit::Visitor {
|
||||
visit_item: visit_item,
|
||||
visit_item: |it, cx: @mut Context, vt| {
|
||||
do cx.with_lint_attrs(it.attrs) {
|
||||
check_item_ctypes(cx, it);
|
||||
check_item_non_camel_case_types(cx, it);
|
||||
check_item_default_methods(cx, it);
|
||||
check_item_heap(cx, it);
|
||||
|
||||
cx.process(Item(it));
|
||||
visit::visit_item(it, cx, vt);
|
||||
}
|
||||
},
|
||||
visit_fn: |fk, decl, body, span, id, cx, vt| {
|
||||
match *fk {
|
||||
visit::fk_method(_, _, m) => {
|
||||
|
@ -386,82 +386,103 @@ pub impl id_range {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> {
|
||||
let visit_generics: @fn(&Generics) = |generics| {
|
||||
pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
|
||||
let visit_generics: @fn(&Generics, T) = |generics, t| {
|
||||
for generics.ty_params.each |p| {
|
||||
vfn(p.id);
|
||||
vfn(p.id, t);
|
||||
}
|
||||
for generics.lifetimes.each |p| {
|
||||
vfn(p.id);
|
||||
vfn(p.id, t);
|
||||
}
|
||||
};
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_mod: |_m, _sp, id| vfn(id),
|
||||
visit::mk_vt(@visit::Visitor {
|
||||
visit_mod: |m, sp, id, t, vt| {
|
||||
vfn(id, t);
|
||||
visit::visit_mod(m, sp, id, t, vt);
|
||||
},
|
||||
|
||||
visit_view_item: |vi| {
|
||||
visit_view_item: |vi, t, vt| {
|
||||
match vi.node {
|
||||
view_item_extern_mod(_, _, id) => vfn(id),
|
||||
view_item_extern_mod(_, _, id) => vfn(id, t),
|
||||
view_item_use(ref vps) => {
|
||||
for vps.each |vp| {
|
||||
match vp.node {
|
||||
view_path_simple(_, _, id) => vfn(id),
|
||||
view_path_glob(_, id) => vfn(id),
|
||||
view_path_simple(_, _, id) => vfn(id, t),
|
||||
view_path_glob(_, id) => vfn(id, t),
|
||||
view_path_list(_, ref paths, id) => {
|
||||
vfn(id);
|
||||
vfn(id, t);
|
||||
for paths.each |p| {
|
||||
vfn(p.node.id);
|
||||
vfn(p.node.id, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
visit::visit_view_item(vi, t, vt);
|
||||
},
|
||||
|
||||
visit_foreign_item: |ni| vfn(ni.id),
|
||||
visit_foreign_item: |ni, t, vt| {
|
||||
vfn(ni.id, t);
|
||||
visit::visit_foreign_item(ni, t, vt);
|
||||
},
|
||||
|
||||
visit_item: |i| {
|
||||
vfn(i.id);
|
||||
visit_item: |i, t, vt| {
|
||||
vfn(i.id, t);
|
||||
match i.node {
|
||||
item_enum(ref enum_definition, _) =>
|
||||
for (*enum_definition).variants.each |v| { vfn(v.node.id); },
|
||||
for (*enum_definition).variants.each |v| { vfn(v.node.id, t); },
|
||||
_ => ()
|
||||
}
|
||||
visit::visit_item(i, t, vt);
|
||||
},
|
||||
|
||||
visit_local: |l| vfn(l.node.id),
|
||||
visit_block: |b| vfn(b.node.id),
|
||||
visit_stmt: |s| vfn(ast_util::stmt_id(s)),
|
||||
visit_arm: |_| {},
|
||||
visit_pat: |p| vfn(p.id),
|
||||
visit_decl: |_| {},
|
||||
|
||||
visit_expr: |e| {
|
||||
vfn(e.callee_id);
|
||||
vfn(e.id);
|
||||
visit_local: |l, t, vt| {
|
||||
vfn(l.node.id, t);
|
||||
visit::visit_local(l, t, vt);
|
||||
},
|
||||
visit_block: |b, t, vt| {
|
||||
vfn(b.node.id, t);
|
||||
visit::visit_block(b, t, vt);
|
||||
},
|
||||
visit_stmt: |s, t, vt| {
|
||||
vfn(ast_util::stmt_id(s), t);
|
||||
visit::visit_stmt(s, t, vt);
|
||||
},
|
||||
visit_pat: |p, t, vt| {
|
||||
vfn(p.id, t);
|
||||
visit::visit_pat(p, t, vt);
|
||||
},
|
||||
|
||||
visit_expr_post: |_| {},
|
||||
visit_expr: |e, t, vt| {
|
||||
vfn(e.callee_id, t);
|
||||
vfn(e.id, t);
|
||||
visit::visit_expr(e, t, vt);
|
||||
},
|
||||
|
||||
visit_ty: |t| {
|
||||
match t.node {
|
||||
ty_path(_, id) => vfn(id),
|
||||
visit_ty: |ty, t, vt| {
|
||||
match ty.node {
|
||||
ty_path(_, id) => vfn(id, t),
|
||||
_ => { /* fall through */ }
|
||||
}
|
||||
visit::visit_ty(ty, t, vt);
|
||||
},
|
||||
|
||||
visit_generics: visit_generics,
|
||||
visit_generics: |generics, t, vt| {
|
||||
visit_generics(generics, t);
|
||||
visit::visit_generics(generics, t, vt);
|
||||
},
|
||||
|
||||
visit_fn: |fk, d, _, _, id| {
|
||||
vfn(id);
|
||||
visit_fn: |fk, d, a, b, id, t, vt| {
|
||||
vfn(id, t);
|
||||
|
||||
match *fk {
|
||||
visit::fk_item_fn(_, generics, _, _) => {
|
||||
visit_generics(generics);
|
||||
visit_generics(generics, t);
|
||||
}
|
||||
visit::fk_method(_, generics, m) => {
|
||||
vfn(m.self_id);
|
||||
visit_generics(generics);
|
||||
vfn(m.self_id, t);
|
||||
visit_generics(generics, t);
|
||||
}
|
||||
visit::fk_anon(_) |
|
||||
visit::fk_fn_block => {
|
||||
@ -469,20 +490,22 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> {
|
||||
}
|
||||
|
||||
for d.inputs.each |arg| {
|
||||
vfn(arg.id)
|
||||
vfn(arg.id, t)
|
||||
}
|
||||
visit::visit_fn(fk, d, a, b, id, t, vt);
|
||||
},
|
||||
|
||||
visit_ty_method: |_| {},
|
||||
visit_trait_method: |_| {},
|
||||
visit_struct_def: |_, _, _, _| {},
|
||||
visit_struct_field: |f| vfn(f.node.id),
|
||||
visit_struct_method: |_| {}
|
||||
visit_struct_field: |f, t, vt| {
|
||||
vfn(f.node.id, t);
|
||||
visit::visit_struct_field(f, t, vt);
|
||||
},
|
||||
|
||||
.. *visit::default_visitor()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(node_id)) {
|
||||
item.accept((), id_visitor(vfn));
|
||||
item.accept((), id_visitor(|id, ()| vfn(id)));
|
||||
}
|
||||
|
||||
pub fn compute_id_range(visit_ids_fn: &fn(@fn(node_id))) -> id_range {
|
||||
|
Loading…
Reference in New Issue
Block a user