Ported check_const from oldvisit to <V:Visitor> trait API.
This commit is contained in:
parent
ef854c9b04
commit
4127c67406
1 changed files with 60 additions and 36 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue