Ported check_const from oldvisit to <V:Visitor> trait API.

This commit is contained in:
Felix S. Klock II 2013-08-13 02:10:10 +02:00
parent ef854c9b04
commit 4127c67406

View file

@ -17,7 +17,30 @@ use util::ppaux;
use syntax::ast::*;
use syntax::codemap;
use syntax::{oldvisit, ast_util, ast_map};
use syntax::{ast_util, ast_map};
use syntax::visit::Visitor;
use syntax::visit;
struct CheckCrateVisitor {
sess: Session,
ast_map: ast_map::map,
def_map: resolve::DefMap,
method_map: typeck::method_map,
tcx: ty::ctxt,
}
impl Visitor<bool> for CheckCrateVisitor {
fn visit_item(&mut self, i:@item, env:bool) {
check_item(self, self.sess, self.ast_map, self.def_map, i, env);
}
fn visit_pat(&mut self, p:@pat, env:bool) {
check_pat(self, p, env);
}
fn visit_expr(&mut self, ex:@expr, env:bool) {
check_expr(self, self.sess, self.def_map, self.method_map,
self.tcx, ex, env);
}
}
pub fn check_crate(sess: Session,
crate: &Crate,
@ -25,39 +48,40 @@ pub fn check_crate(sess: Session,
def_map: resolve::DefMap,
method_map: typeck::method_map,
tcx: ty::ctxt) {
oldvisit::visit_crate(crate, (false, oldvisit::mk_vt(@oldvisit::Visitor {
visit_item: |a,b| check_item(sess, ast_map, def_map, a, b),
visit_pat: check_pat,
visit_expr: |a,b|
check_expr(sess, def_map, method_map, tcx, a, b),
.. *oldvisit::default_visitor()
})));
let mut v = CheckCrateVisitor {
sess: sess,
ast_map: ast_map,
def_map: def_map,
method_map: method_map,
tcx: tcx,
};
visit::walk_crate(&mut v, crate, false);
sess.abort_if_errors();
}
pub fn check_item(sess: Session,
pub fn check_item(v: &mut CheckCrateVisitor,
sess: Session,
ast_map: ast_map::map,
def_map: resolve::DefMap,
it: @item,
(_is_const, v): (bool,
oldvisit::vt<bool>)) {
_is_const: bool) {
match it.node {
item_static(_, _, ex) => {
(v.visit_expr)(ex, (true, v));
v.visit_expr(ex, true);
check_item_recursion(sess, ast_map, def_map, it);
}
item_enum(ref enum_definition, _) => {
for var in (*enum_definition).variants.iter() {
for ex in var.node.disr_expr.iter() {
(v.visit_expr)(*ex, (true, v));
v.visit_expr(*ex, true);
}
}
}
_ => oldvisit::visit_item(it, (false, v))
_ => visit::walk_item(v, it, false)
}
}
pub fn check_pat(p: @pat, (_is_const, v): (bool, oldvisit::vt<bool>)) {
pub fn check_pat(v: &mut CheckCrateVisitor, p: @pat, _is_const: bool) {
fn is_str(e: @expr) -> bool {
match e.node {
expr_vstore(
@ -72,22 +96,22 @@ pub fn check_pat(p: @pat, (_is_const, v): (bool, oldvisit::vt<bool>)) {
}
match p.node {
// Let through plain ~-string literals here
pat_lit(a) => if !is_str(a) { (v.visit_expr)(a, (true, v)); },
pat_lit(a) => if !is_str(a) { v.visit_expr(a, true); },
pat_range(a, b) => {
if !is_str(a) { (v.visit_expr)(a, (true, v)); }
if !is_str(b) { (v.visit_expr)(b, (true, v)); }
if !is_str(a) { v.visit_expr(a, true); }
if !is_str(b) { v.visit_expr(b, true); }
}
_ => oldvisit::visit_pat(p, (false, v))
_ => visit::walk_pat(v, p, false)
}
}
pub fn check_expr(sess: Session,
pub fn check_expr(v: &mut CheckCrateVisitor,
sess: Session,
def_map: resolve::DefMap,
method_map: typeck::method_map,
tcx: ty::ctxt,
e: @expr,
(is_const, v): (bool,
oldvisit::vt<bool>)) {
is_const: bool) {
if is_const {
match e.node {
expr_unary(_, deref, _) => { }
@ -152,8 +176,8 @@ pub fn check_expr(sess: Session,
}
}
}
expr_paren(e) => { check_expr(sess, def_map, method_map,
tcx, e, (is_const, v)); }
expr_paren(e) => { check_expr(v, sess, def_map, method_map,
tcx, e, is_const); }
expr_vstore(_, expr_vstore_slice) |
expr_vec(_, m_imm) |
expr_addr_of(m_imm, _) |
@ -191,7 +215,7 @@ pub fn check_expr(sess: Session,
}
_ => ()
}
oldvisit::visit_expr(e, (is_const, v));
visit::walk_expr(v, e, is_const);
}
#[deriving(Clone)]
@ -203,6 +227,8 @@ struct env {
idstack: @mut ~[NodeId]
}
struct CheckItemRecursionVisitor;
// Make sure a const item doesn't recursively refer to itself
// FIXME: Should use the dependency graph when it's available (#1356)
pub fn check_item_recursion(sess: Session,
@ -217,29 +243,27 @@ pub fn check_item_recursion(sess: Session,
idstack: @mut ~[]
};
let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
visit_item: visit_item,
visit_expr: visit_expr,
.. *oldvisit::default_visitor()
});
(visitor.visit_item)(it, (env, visitor));
let mut visitor = CheckItemRecursionVisitor;
visitor.visit_item(it, env);
}
fn visit_item(it: @item, (env, v): (env, oldvisit::vt<env>)) {
impl Visitor<env> for CheckItemRecursionVisitor {
fn visit_item(&mut self, it: @item, env: env) {
if env.idstack.iter().any(|x| x == &(it.id)) {
env.sess.span_fatal(env.root_it.span, "recursive constant");
}
env.idstack.push(it.id);
oldvisit::visit_item(it, (env, v));
visit::walk_item(self, it, env);
env.idstack.pop();
}
fn visit_expr(e: @expr, (env, v): (env, oldvisit::vt<env>)) {
fn visit_expr(&mut self, e: @expr, env: env) {
match e.node {
expr_path(*) => match env.def_map.find(&e.id) {
Some(&def_static(def_id, _)) if ast_util::is_local(def_id) =>
match env.ast_map.get_copy(&def_id.node) {
ast_map::node_item(it, _) => {
(v.visit_item)(it, (env, v));
self.visit_item(it, env);
}
_ => fail!("const not bound to an item")
},
@ -247,6 +271,6 @@ pub fn check_item_recursion(sess: Session,
},
_ => ()
}
oldvisit::visit_expr(e, (env, v));
visit::walk_expr(self, e, env);
}
}