auto merge of #8623 : pnkfelix/rust/fsk-visitor-vpar-defaults-step4, r=nmatsakis

Follow up to #8619 (step 3 of 5).

(See #8527, which was step 1 of 5, for the full outline.)

Part of #7081.
This commit is contained in:
bors 2013-08-19 15:02:07 -07:00
commit e6e678fac7
8 changed files with 314 additions and 217 deletions

View file

@ -27,7 +27,8 @@ use syntax::ast::{m_mutbl, m_imm, m_const};
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::span;
use syntax::oldvisit;
use syntax::visit;
use syntax::visit::Visitor;
use util::ppaux::Repr;
#[deriving(Clone)]
@ -39,6 +40,27 @@ struct CheckLoanCtxt<'self> {
reported: @mut HashSet<ast::NodeId>,
}
struct CheckLoanVisitor;
impl<'self> Visitor<CheckLoanCtxt<'self>> for CheckLoanVisitor {
fn visit_expr<'a>(&mut self, ex:@ast::expr, e:CheckLoanCtxt<'a>) {
check_loans_in_expr(self, ex, e);
}
fn visit_local(&mut self, l:@ast::Local, e:CheckLoanCtxt) {
check_loans_in_local(self, l, e);
}
fn visit_block(&mut self, b:&ast::Block, e:CheckLoanCtxt) {
check_loans_in_block(self, b, e);
}
fn visit_pat(&mut self, p:@ast::pat, e:CheckLoanCtxt) {
check_loans_in_pat(self, p, e);
}
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
b:&ast::Block, s:span, n:ast::NodeId, e:CheckLoanCtxt) {
check_loans_in_fn(self, fk, fd, b, s, n, e);
}
}
pub fn check_loans(bccx: @BorrowckCtxt,
dfcx_loans: &LoanDataFlow,
move_data: move_data::FlowedMoveData,
@ -54,15 +76,8 @@ pub fn check_loans(bccx: @BorrowckCtxt,
reported: @mut HashSet::new(),
};
let vt = oldvisit::mk_vt(@oldvisit::Visitor {
visit_expr: check_loans_in_expr,
visit_local: check_loans_in_local,
visit_block: check_loans_in_block,
visit_pat: check_loans_in_pat,
visit_fn: check_loans_in_fn,
.. *oldvisit::default_visitor()
});
(vt.visit_block)(body, (clcx, vt));
let mut vt = CheckLoanVisitor;
vt.visit_block(body, clcx);
}
enum MoveError {
@ -626,27 +641,27 @@ impl<'self> CheckLoanCtxt<'self> {
}
}
fn check_loans_in_fn<'a>(fk: &oldvisit::fn_kind,
fn check_loans_in_fn<'a>(visitor: &mut CheckLoanVisitor,
fk: &visit::fn_kind,
decl: &ast::fn_decl,
body: &ast::Block,
sp: span,
id: ast::NodeId,
(this, visitor): (CheckLoanCtxt<'a>,
oldvisit::vt<CheckLoanCtxt<'a>>)) {
this: CheckLoanCtxt<'a>) {
match *fk {
oldvisit::fk_item_fn(*) |
oldvisit::fk_method(*) => {
visit::fk_item_fn(*) |
visit::fk_method(*) => {
// Don't process nested items.
return;
}
oldvisit::fk_anon(*) |
oldvisit::fk_fn_block(*) => {
visit::fk_anon(*) |
visit::fk_fn_block(*) => {
check_captured_variables(this, id, sp);
}
}
oldvisit::visit_fn(fk, decl, body, sp, id, (this, visitor));
visit::walk_fn(visitor, fk, decl, body, sp, id, this);
fn check_captured_variables(this: CheckLoanCtxt,
closure_id: ast::NodeId,
@ -689,16 +704,16 @@ fn check_loans_in_fn<'a>(fk: &oldvisit::fn_kind,
}
}
fn check_loans_in_local<'a>(local: @ast::Local,
(this, vt): (CheckLoanCtxt<'a>,
oldvisit::vt<CheckLoanCtxt<'a>>)) {
oldvisit::visit_local(local, (this, vt));
fn check_loans_in_local<'a>(vt: &mut CheckLoanVisitor,
local: @ast::Local,
this: CheckLoanCtxt<'a>) {
visit::walk_local(vt, local, this);
}
fn check_loans_in_expr<'a>(expr: @ast::expr,
(this, vt): (CheckLoanCtxt<'a>,
oldvisit::vt<CheckLoanCtxt<'a>>)) {
oldvisit::visit_expr(expr, (this, vt));
fn check_loans_in_expr<'a>(vt: &mut CheckLoanVisitor,
expr: @ast::expr,
this: CheckLoanCtxt<'a>) {
visit::walk_expr(vt, expr, this);
debug!("check_loans_in_expr(expr=%s)",
expr.repr(this.tcx()));
@ -749,19 +764,19 @@ fn check_loans_in_expr<'a>(expr: @ast::expr,
}
}
fn check_loans_in_pat<'a>(pat: @ast::pat,
(this, vt): (CheckLoanCtxt<'a>,
oldvisit::vt<CheckLoanCtxt<'a>>))
fn check_loans_in_pat<'a>(vt: &mut CheckLoanVisitor,
pat: @ast::pat,
this: CheckLoanCtxt<'a>)
{
this.check_for_conflicting_loans(pat.id);
this.check_move_out_from_id(pat.id, pat.span);
oldvisit::visit_pat(pat, (this, vt));
visit::walk_pat(vt, pat, this);
}
fn check_loans_in_block<'a>(blk: &ast::Block,
(this, vt): (CheckLoanCtxt<'a>,
oldvisit::vt<CheckLoanCtxt<'a>>))
fn check_loans_in_block<'a>(vt: &mut CheckLoanVisitor,
blk: &ast::Block,
this: CheckLoanCtxt<'a>)
{
oldvisit::visit_block(blk, (this, vt));
visit::walk_block(vt, blk, this);
this.check_for_conflicting_loans(blk.id);
}

View file

@ -15,9 +15,9 @@ use syntax::ast::{Crate, NodeId, item, item_fn};
use syntax::ast_map;
use syntax::attr;
use syntax::codemap::span;
use syntax::oldvisit::{default_visitor, mk_vt, vt, Visitor, visit_crate};
use syntax::oldvisit::{visit_item};
use syntax::parse::token::special_idents;
use syntax::visit;
use syntax::visit::Visitor;
use std::util;
struct EntryContext {
@ -39,7 +39,13 @@ struct EntryContext {
non_main_fns: ~[(NodeId, span)],
}
type EntryVisitor = vt<@mut EntryContext>;
struct EntryVisitor;
impl Visitor<@mut EntryContext> for EntryVisitor {
fn visit_item(&mut self, item:@item, ctxt:@mut EntryContext) {
find_item(item, ctxt, self);
}
}
pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map) {
@ -65,15 +71,14 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map)
non_main_fns: ~[],
};
visit_crate(crate, (ctxt, mk_vt(@Visitor {
visit_item: |item, (ctxt, visitor)| find_item(item, ctxt, visitor),
.. *default_visitor()
})));
let mut v = EntryVisitor;
visit::walk_crate(&mut v, crate, ctxt);
configure_main(ctxt);
}
fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) {
fn find_item(item: @item, ctxt: @mut EntryContext, visitor: &mut EntryVisitor) {
match item.node {
item_fn(*) => {
if item.ident == special_idents::main {
@ -120,7 +125,7 @@ fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) {
_ => ()
}
visit_item(item, (ctxt, visitor));
visit::walk_item(visitor, item, ctxt);
}
fn configure_main(ctxt: @mut EntryContext) {

View file

@ -17,7 +17,10 @@ use middle::ty;
use std::hashmap::HashMap;
use syntax::codemap::span;
use syntax::{ast, ast_util, oldvisit};
use syntax::{ast, ast_util};
use syntax::visit;
use syntax::visit::Visitor;
use syntax::ast::{item};
// A vector of defs representing the free variables referred to in a function.
// (The def_upvar will already have been stripped).
@ -29,27 +32,27 @@ pub struct freevar_entry {
pub type freevar_info = @~[@freevar_entry];
pub type freevar_map = @mut HashMap<ast::NodeId, freevar_info>;
// Searches through part of the AST for all references to locals or
// upvars in this frame and returns the list of definition IDs thus found.
// Since we want to be able to collect upvars in some arbitrary piece
// of the AST, we take a walker function that we invoke with a visitor
// in order to start the search.
fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
-> freevar_info {
let seen = @mut HashMap::new();
let refs = @mut ~[];
struct CollectFreevarsVisitor {
seen: @mut HashMap<ast::NodeId, ()>,
refs: @mut ~[@freevar_entry],
def_map: resolve::DefMap,
}
fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt<int>)) { }
impl Visitor<int> for CollectFreevarsVisitor {
fn visit_item(&mut self, _:@item, _:int) {
// ignore_item
}
fn visit_expr(&mut self, expr:@ast::expr, depth:int) {
let walk_expr: @fn(expr: @ast::expr, (int, oldvisit::vt<int>)) =
|expr, (depth, v)| {
match expr.node {
ast::expr_fn_block(*) => {
oldvisit::visit_expr(expr, (depth + 1, v))
visit::walk_expr(self, expr, depth + 1)
}
ast::expr_path(*) | ast::expr_self => {
let mut i = 0;
match def_map.find(&expr.id) {
match self.def_map.find(&expr.id) {
None => fail!("path not found"),
Some(&df) => {
let mut def = df;
@ -62,28 +65,58 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
}
if i == depth { // Made it to end of loop
let dnum = ast_util::def_id_of_def(def).node;
if !seen.contains_key(&dnum) {
refs.push(@freevar_entry {
if !self.seen.contains_key(&dnum) {
self.refs.push(@freevar_entry {
def: def,
span: expr.span,
});
seen.insert(dnum, ());
self.seen.insert(dnum, ());
}
}
}
}
}
_ => oldvisit::visit_expr(expr, (depth, v))
_ => visit::walk_expr(self, expr, depth)
}
};
}
let v = oldvisit::mk_vt(@oldvisit::Visitor {visit_item: ignore_item,
visit_expr: walk_expr,
.. *oldvisit::default_visitor()});
(v.visit_block)(blk, (1, v));
}
// Searches through part of the AST for all references to locals or
// upvars in this frame and returns the list of definition IDs thus found.
// Since we want to be able to collect upvars in some arbitrary piece
// of the AST, we take a walker function that we invoke with a visitor
// in order to start the search.
fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block)
-> freevar_info {
let seen = @mut HashMap::new();
let refs = @mut ~[];
let mut v = CollectFreevarsVisitor {
seen: seen,
refs: refs,
def_map: def_map,
};
v.visit_block(blk, 1);
return @(*refs).clone();
}
struct AnnotateFreevarsVisitor {
def_map: resolve::DefMap,
freevars: freevar_map,
}
impl Visitor<()> for AnnotateFreevarsVisitor {
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
blk:&ast::Block, s:span, nid:ast::NodeId, _:()) {
let vars = collect_freevars(self.def_map, blk);
self.freevars.insert(nid, vars);
visit::walk_fn(self, fk, fd, blk, s, nid, ());
}
}
// Build a map from every function and for-each body to a set of the
// freevars contained in it. The implementation is not particularly
// efficient as it fully recomputes the free variables at every
@ -93,20 +126,11 @@ pub fn annotate_freevars(def_map: resolve::DefMap, crate: &ast::Crate) ->
freevar_map {
let freevars = @mut HashMap::new();
let walk_fn: @fn(&oldvisit::fn_kind,
&ast::fn_decl,
&ast::Block,
span,
ast::NodeId) = |_, _, blk, _, nid| {
let vars = collect_freevars(def_map, blk);
freevars.insert(nid, vars);
let mut visitor = AnnotateFreevarsVisitor {
def_map: def_map,
freevars: freevars,
};
let visitor =
oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor {
visit_fn: walk_fn,
.. *oldvisit::default_simple_visitor()});
oldvisit::visit_crate(crate, ((), visitor));
visit::walk_crate(&mut visitor, crate, ());
return freevars;
}

View file

@ -21,7 +21,8 @@ use syntax::attr;
use syntax::codemap::span;
use syntax::opt_vec;
use syntax::print::pprust::expr_to_str;
use syntax::{oldvisit, ast_util};
use syntax::{visit,ast_util};
use syntax::visit::Visitor;
// Kind analysis pass.
//
@ -58,6 +59,29 @@ pub struct Context {
current_item: NodeId
}
struct KindAnalysisVisitor;
impl Visitor<Context> for KindAnalysisVisitor {
fn visit_expr(&mut self, ex:@expr, e:Context) {
check_expr(self, ex, e);
}
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&fn_decl, b:&Block, s:span, n:NodeId, e:Context) {
check_fn(self, fk, fd, b, s, n, e);
}
fn visit_ty(&mut self, t:&Ty, e:Context) {
check_ty(self, t, e);
}
fn visit_item(&mut self, i:@item, e:Context) {
check_item(self, i, e);
}
fn visit_block(&mut self, b:&Block, e:Context) {
check_block(self, b, e);
}
}
pub fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
crate: &Crate) {
@ -66,15 +90,8 @@ pub fn check_crate(tcx: ty::ctxt,
method_map: method_map,
current_item: -1
};
let visit = oldvisit::mk_vt(@oldvisit::Visitor {
visit_expr: check_expr,
visit_fn: check_fn,
visit_ty: check_ty,
visit_item: check_item,
visit_block: check_block,
.. *oldvisit::default_visitor()
});
oldvisit::visit_crate(crate, (ctx, visit));
let mut visit = KindAnalysisVisitor;
visit::walk_crate(&mut visit, crate, ctx);
tcx.sess.abort_if_errors();
}
@ -108,12 +125,13 @@ fn check_struct_safe_for_destructor(cx: Context,
}
}
fn check_block(block: &Block,
(cx, visitor): (Context, oldvisit::vt<Context>)) {
oldvisit::visit_block(block, (cx, visitor));
fn check_block(visitor: &mut KindAnalysisVisitor,
block: &Block,
cx: Context) {
visit::walk_block(visitor, block, cx);
}
fn check_item(item: @item, (cx, visitor): (Context, oldvisit::vt<Context>)) {
fn check_item(visitor: &mut KindAnalysisVisitor, item: @item, cx: Context) {
// If this is a destructor, check kinds.
if !attr::contains_name(item.attrs, "unsafe_destructor") {
match item.node {
@ -153,7 +171,7 @@ fn check_item(item: @item, (cx, visitor): (Context, oldvisit::vt<Context>)) {
}
let cx = Context { current_item: item.id, ..cx };
oldvisit::visit_item(item, (cx, visitor));
visit::walk_item(visitor, item, cx);
}
// Yields the appropriate function to check the kind of closed over
@ -227,13 +245,13 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
// Check that the free variables used in a shared/sendable closure conform
// to the copy/move kind bounds. Then recursively check the function body.
fn check_fn(
fk: &oldvisit::fn_kind,
v: &mut KindAnalysisVisitor,
fk: &visit::fn_kind,
decl: &fn_decl,
body: &Block,
sp: span,
fn_id: NodeId,
(cx, v): (Context,
oldvisit::vt<Context>)) {
cx: Context) {
// Check kinds on free variables:
do with_appropriate_checker(cx, fn_id) |chk| {
@ -243,10 +261,10 @@ fn check_fn(
}
}
oldvisit::visit_fn(fk, decl, body, sp, fn_id, (cx, v));
visit::walk_fn(v, fk, decl, body, sp, fn_id, cx);
}
pub fn check_expr(e: @expr, (cx, v): (Context, oldvisit::vt<Context>)) {
pub fn check_expr(v: &mut KindAnalysisVisitor, e: @expr, cx: Context) {
debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr()));
// Handle any kind bounds on type parameters
@ -311,10 +329,10 @@ pub fn check_expr(e: @expr, (cx, v): (Context, oldvisit::vt<Context>)) {
}
_ => {}
}
oldvisit::visit_expr(e, (cx, v));
visit::walk_expr(v, e, cx);
}
fn check_ty(aty: &Ty, (cx, v): (Context, oldvisit::vt<Context>)) {
fn check_ty(v: &mut KindAnalysisVisitor, aty: &Ty, cx: Context) {
match aty.node {
ty_path(_, _, id) => {
let r = cx.tcx.node_type_substs.find(&id);
@ -329,7 +347,7 @@ fn check_ty(aty: &Ty, (cx, v): (Context, oldvisit::vt<Context>)) {
}
_ => {}
}
oldvisit::visit_ty(aty, (cx, v));
visit::walk_ty(v, aty, cx);
}
// Calls "any_missing" if any bounds were missing.

View file

@ -26,8 +26,9 @@ use metadata::cstore::iter_crate_data;
use syntax::ast::{Crate, def_id, MetaItem};
use syntax::ast_util::local_def;
use syntax::attr::AttrMetaMethods;
use syntax::oldvisit::{default_simple_visitor, mk_simple_visitor};
use syntax::oldvisit::{SimpleVisitor, visit_crate};
use syntax::ast::{item};
use syntax::visit;
use syntax::visit::Visitor;
use std::hashmap::HashMap;
@ -292,6 +293,27 @@ struct LanguageItemCollector<'self> {
item_refs: HashMap<@str, uint>,
}
struct LanguageItemVisitor<'self> {
this: *mut LanguageItemCollector<'self>,
}
impl<'self> Visitor<()> for LanguageItemVisitor<'self> {
fn visit_item(&mut self, item:@item, _:()) {
for attribute in item.attrs.iter() {
unsafe {
(*self.this).match_and_collect_meta_item(
local_def(item.id),
attribute.node.value
);
}
}
visit::walk_item(self, item, ());
}
}
impl<'self> LanguageItemCollector<'self> {
pub fn new<'a>(crate: &'a Crate, session: Session)
-> LanguageItemCollector<'a> {
@ -404,19 +426,8 @@ impl<'self> LanguageItemCollector<'self> {
pub fn collect_local_language_items(&mut self) {
let this: *mut LanguageItemCollector = &mut *self;
visit_crate(self.crate, ((), mk_simple_visitor(@SimpleVisitor {
visit_item: |item| {
for attribute in item.attrs.iter() {
unsafe {
(*this).match_and_collect_meta_item(
local_def(item.id),
attribute.node.value
);
}
}
},
.. *default_simple_visitor()
})));
let mut v = LanguageItemVisitor { this: this };
visit::walk_crate(&mut v, self.crate, ());
}
pub fn collect_external_language_items(&mut self) {

View file

@ -45,10 +45,7 @@ use syntax::ast_map;
use syntax::ast_util::{def_id_of_def, local_def};
use syntax::codemap::{span, dummy_sp};
use syntax::opt_vec;
use syntax::oldvisit::{default_simple_visitor, default_visitor};
use syntax::oldvisit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
use syntax::oldvisit::{Visitor, SimpleVisitor};
use syntax::oldvisit::{visit_mod};
use syntax::visit;
use syntax::parse;
use util::ppaux::ty_to_str;
@ -168,15 +165,13 @@ pub struct CoherenceChecker {
base_type_def_ids: @mut HashMap<def_id,def_id>,
}
impl CoherenceChecker {
pub fn check_coherence(self, crate: &Crate) {
// Check implementations and traits. This populates the tables
// containing the inherent methods and extension methods. It also
// builds up the trait inheritance table.
visit_crate(crate, ((), mk_simple_visitor(@SimpleVisitor {
visit_item: |item| {
struct CoherenceCheckVisitor { cc: CoherenceChecker }
impl visit::Visitor<()> for CoherenceCheckVisitor {
fn visit_item(&mut self, item:@item, _:()) {
// debug!("(checking coherence) item '%s'",
// self.crate_context.tcx.sess.str_of(item.ident));
// self.cc.crate_context.tcx.sess.str_of(item.ident));
match item.node {
item_impl(_, ref opt_trait, _, _) => {
@ -184,15 +179,75 @@ impl CoherenceChecker {
opt_trait.iter()
.map(|x| (*x).clone())
.collect();
self.check_implementation(item, opt_trait);
self.cc.check_implementation(item, opt_trait);
}
_ => {
// Nothing to do.
}
};
},
.. *default_simple_visitor()
})));
visit::walk_item(self, item, ());
}
}
struct PrivilegedScopeVisitor { cc: CoherenceChecker }
impl visit::Visitor<()> for PrivilegedScopeVisitor {
fn visit_item(&mut self, item:@item, _:()) {
match item.node {
item_mod(ref module_) => {
// Then visit the module items.
visit::walk_mod(self, module_, ());
}
item_impl(_, None, ref ast_ty, _) => {
if !self.cc.ast_type_is_defined_in_local_crate(ast_ty) {
// This is an error.
let session = self.cc.crate_context.tcx.sess;
session.span_err(item.span,
"cannot associate methods with a type outside the \
crate the type is defined in; define and implement \
a trait or new type instead");
}
}
item_impl(_, Some(ref trait_ref), _, _) => {
// `for_ty` is `Type` in `impl Trait for Type`
let for_ty =
ty::node_id_to_type(self.cc.crate_context.tcx,
item.id);
if !type_is_defined_in_local_crate(for_ty) {
// This implementation is not in scope of its base
// type. This still might be OK if the trait is
// defined in the same crate.
let trait_def_id =
self.cc.trait_ref_to_trait_def_id(trait_ref);
if trait_def_id.crate != LOCAL_CRATE {
let session = self.cc.crate_context.tcx.sess;
session.span_err(item.span,
"cannot provide an extension implementation \
for a trait not defined in this crate");
}
}
visit::walk_item(self, item, ());
}
_ => {
visit::walk_item(self, item, ());
}
}
}
}
impl CoherenceChecker {
pub fn check_coherence(self, crate: &Crate) {
// Check implementations and traits. This populates the tables
// containing the inherent methods and extension methods. It also
// builds up the trait inheritance table.
let mut visitor = CoherenceCheckVisitor { cc: self };
visit::walk_crate(&mut visitor, crate, ());
// Check that there are no overlapping trait instances
self.check_implementation_coherence();
@ -486,53 +541,8 @@ impl CoherenceChecker {
// Privileged scope checking
pub fn check_privileged_scopes(self, crate: &Crate) {
visit_crate(crate, ((), mk_vt(@Visitor {
visit_item: |item, (_context, visitor)| {
match item.node {
item_mod(ref module_) => {
// Then visit the module items.
visit_mod(module_, item.span, item.id, ((), visitor));
}
item_impl(_, None, ref ast_ty, _) => {
if !self.ast_type_is_defined_in_local_crate(ast_ty) {
// This is an error.
let session = self.crate_context.tcx.sess;
session.span_err(item.span,
"cannot associate methods with a type outside the \
crate the type is defined in; define and implement \
a trait or new type instead");
}
}
item_impl(_, Some(ref trait_ref), _, _) => {
// `for_ty` is `Type` in `impl Trait for Type`
let for_ty =
ty::node_id_to_type(self.crate_context.tcx,
item.id);
if !type_is_defined_in_local_crate(for_ty) {
// This implementation is not in scope of its base
// type. This still might be OK if the trait is
// defined in the same crate.
let trait_def_id =
self.trait_ref_to_trait_def_id(trait_ref);
if trait_def_id.crate != LOCAL_CRATE {
let session = self.crate_context.tcx.sess;
session.span_err(item.span,
"cannot provide an extension implementation \
for a trait not defined in this crate");
}
}
visit_item(item, ((), visitor));
}
_ => {
visit_item(item, ((), visitor));
}
}
},
.. *default_visitor()
})));
let mut visitor = PrivilegedScopeVisitor{ cc: self };
visit::walk_crate(&mut visitor, crate, ());
}
pub fn trait_ref_to_trait_def_id(&self, trait_ref: &trait_ref) -> def_id {

View file

@ -11,7 +11,8 @@
use syntax::ast;
use syntax::codemap::{span};
use syntax::oldvisit;
use syntax::visit;
use syntax::visit::Visitor;
use std::hashmap::HashSet;
use extra;
@ -59,42 +60,48 @@ pub fn field_exprs(fields: ~[ast::Field]) -> ~[@ast::expr] {
fields.map(|f| f.expr)
}
// Takes a predicate p, returns true iff p is true for any subexpressions
// of b -- skipping any inner loops (loop, while, loop_body)
pub fn loop_query(b: &ast::Block, p: @fn(&ast::expr_) -> bool) -> bool {
let rs = @mut false;
let visit_expr: @fn(@ast::expr,
(@mut bool,
oldvisit::vt<@mut bool>)) = |e, (flag, v)| {
*flag |= p(&e.node);
struct LoopQueryVisitor {
p: @fn(&ast::expr_) -> bool
}
impl Visitor<@mut bool> for LoopQueryVisitor {
fn visit_expr(&mut self, e:@ast::expr, flag:@mut bool) {
*flag |= (self.p)(&e.node);
match e.node {
// Skip inner loops, since a break in the inner loop isn't a
// break inside the outer loop
ast::expr_loop(*) | ast::expr_while(*) => {}
_ => oldvisit::visit_expr(e, (flag, v))
_ => visit::walk_expr(self, e, flag)
}
};
let v = oldvisit::mk_vt(@oldvisit::Visitor {
visit_expr: visit_expr,
.. *oldvisit::default_visitor()});
oldvisit::visit_block(b, (rs, v));
}
}
// Takes a predicate p, returns true iff p is true for any subexpressions
// of b -- skipping any inner loops (loop, while, loop_body)
pub fn loop_query(b: &ast::Block, p: @fn(&ast::expr_) -> bool) -> bool {
let rs = @mut false;
let mut v = LoopQueryVisitor { p: p };
visit::walk_block(&mut v, b, rs);
return *rs;
}
struct BlockQueryVisitor {
p: @fn(@ast::expr) -> bool
}
impl Visitor<@mut bool> for BlockQueryVisitor {
fn visit_expr(&mut self, e:@ast::expr, flag:@mut bool) {
*flag |= (self.p)(e);
visit::walk_expr(self, e, flag)
}
}
// Takes a predicate p, returns true iff p is true for any subexpressions
// of b -- skipping any inner loops (loop, while, loop_body)
pub fn block_query(b: &ast::Block, p: @fn(@ast::expr) -> bool) -> bool {
let rs = @mut false;
let visit_expr: @fn(@ast::expr,
(@mut bool,
oldvisit::vt<@mut bool>)) = |e, (flag, v)| {
*flag |= p(e);
oldvisit::visit_expr(e, (flag, v))
};
let v = oldvisit::mk_vt(@oldvisit::Visitor{
visit_expr: visit_expr,
.. *oldvisit::default_visitor()});
oldvisit::visit_block(b, (rs, v));
let mut v = BlockQueryVisitor { p: p };
visit::walk_block(&mut v, b, rs);
return *rs;
}

View file

@ -13,24 +13,31 @@ use syntax::ast;
use syntax::print::pp;
use syntax::print::pprust;
use syntax::parse::token;
use syntax::visit;
pub fn each_binding(l: @ast::Local, f: @fn(&ast::Path, ast::NodeId)) {
use syntax::oldvisit;
struct EachBindingVisitor {
f: @fn(&ast::Path, ast::NodeId)
}
let vt = oldvisit::mk_simple_visitor(
@oldvisit::SimpleVisitor {
visit_pat: |pat| {
impl visit::Visitor<()> for EachBindingVisitor {
fn visit_pat(&mut self, pat:@ast::pat, _:()) {
match pat.node {
ast::pat_ident(_, ref path, _) => {
f(path, pat.id);
(self.f)(path, pat.id);
}
_ => {}
}
},
.. *oldvisit::default_simple_visitor()
}
);
(vt.visit_pat)(l.pat, ((), vt));
visit::walk_pat(self, pat, ());
}
}
pub fn each_binding(l: @ast::Local, f: @fn(&ast::Path, ast::NodeId)) {
use syntax::visit::Visitor;
let mut vt = EachBindingVisitor{ f: f };
vt.visit_pat(l.pat, ());
}
/// A utility function that hands off a pretty printer to a callback.