Skip to content

visitor trait rewrite step 4 (of 5). #8623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
83 changes: 49 additions & 34 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()));
Expand Down Expand Up @@ -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);
}
23 changes: 14 additions & 9 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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) {

Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
98 changes: 61 additions & 37 deletions src/librustc/middle/freevars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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,
}

impl Visitor<int> for CollectFreevarsVisitor {

fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt<int>)) { }
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;
Expand All @@ -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
Expand All @@ -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;
}
Expand Down
Loading