use syntax::visit::Visitor;
use syntax::visit;
-struct CheckCrateVisitor {
- sess: Session,
- ast_map: ast_map::Map,
+pub struct CheckCrateVisitor<'a> {
def_map: resolve::DefMap,
- method_map: typeck::method_map,
- tcx: ty::ctxt,
+ method_map: typeck::MethodMap,
+ tcx: &'a ty::ctxt,
}
-impl Visitor<bool> for CheckCrateVisitor {
+impl<'a> Visitor<bool> for CheckCrateVisitor<'a> {
fn visit_item(&mut self, i: &Item, env: bool) {
- check_item(self, self.sess, self.ast_map, self.def_map, i, env);
+ check_item(self, 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);
+ check_expr(self, ex, env);
}
}
-pub fn check_crate(sess: Session,
- crate: &Crate,
- ast_map: ast_map::Map,
+pub fn check_crate(krate: &Crate,
def_map: resolve::DefMap,
- method_map: typeck::method_map,
- tcx: ty::ctxt) {
+ method_map: typeck::MethodMap,
+ tcx: &ty::ctxt) {
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();
+ visit::walk_crate(&mut v, krate, false);
+ tcx.sess.abort_if_errors();
}
-pub fn check_item(v: &mut CheckCrateVisitor,
- sess: Session,
- ast_map: ast_map::Map,
- def_map: resolve::DefMap,
- it: &Item,
- _is_const: bool) {
+fn check_item(v: &mut CheckCrateVisitor, it: &Item, _is_const: bool) {
match it.node {
ItemStatic(_, _, ex) => {
v.visit_expr(ex, true);
- check_item_recursion(sess, ast_map, def_map, it);
+ check_item_recursion(&v.tcx.sess, &v.tcx.map, v.def_map, it);
}
ItemEnum(ref enum_definition, _) => {
for var in (*enum_definition).variants.iter() {
}
}
-pub fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
- fn is_str(e: @Expr) -> bool {
+fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
+ fn is_str(e: &Expr) -> bool {
match e.node {
ExprVstore(expr, ExprVstoreUniq) => {
match expr.node {
}
}
-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: bool) {
+fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
if is_const {
match e.node {
- ExprUnary(_, UnDeref, _) => { }
- ExprUnary(_, UnBox, _) | ExprUnary(_, UnUniq, _) => {
- sess.span_err(e.span,
- "cannot do allocations in constant expressions");
+ ExprUnary(UnDeref, _) => { }
+ ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
+ v.tcx.sess.span_err(e.span,
+ "cannot do allocations in constant expressions");
return;
}
ExprLit(lit) if ast_util::lit_is_str(lit) => {}
ExprBinary(..) | ExprUnary(..) => {
- let method_map = method_map.borrow();
- if method_map.get().contains_key(&e.id) {
- sess.span_err(e.span, "user-defined operators are not \
- allowed in constant expressions");
+ let method_call = typeck::MethodCall::expr(e.id);
+ if v.method_map.borrow().contains_key(&method_call) {
+ v.tcx.sess.span_err(e.span, "user-defined operators are not \
+ allowed in constant expressions");
}
}
ExprLit(_) => (),
ExprCast(_, _) => {
- let ety = ty::expr_ty(tcx, e);
+ let ety = ty::expr_ty(v.tcx, e);
if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
- sess.span_err(e.span, ~"can not cast to `" +
- ppaux::ty_to_str(tcx, ety) +
- "` in a constant expression");
+ v.tcx.sess.span_err(e.span, "can not cast to `".to_owned() +
+ ppaux::ty_to_str(v.tcx, ety) +
+ "` in a constant expression");
}
}
ExprPath(ref pth) => {
// foo::<bar> in a const. Currently that is only done on
// a path in trans::callee that only works in block contexts.
if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
- sess.span_err(
- e.span, "paths in constants may only refer to \
- items without type parameters");
+ v.tcx.sess.span_err(e.span,
+ "paths in constants may only refer to \
+ items without type parameters");
}
- let def_map = def_map.borrow();
- match def_map.get().find(&e.id) {
+ match v.def_map.borrow().find(&e.id) {
Some(&DefStatic(..)) |
Some(&DefFn(_, _)) |
Some(&DefVariant(_, _, _)) |
Some(&def) => {
debug!("(checking const) found bad def: {:?}", def);
- sess.span_err(
- e.span,
+ v.tcx.sess.span_err(e.span,
"paths in constants may only refer to \
constants or functions");
}
None => {
- sess.span_bug(e.span, "unbound path in const?!");
+ v.tcx.sess.span_bug(e.span, "unbound path in const?!");
}
}
}
- ExprCall(callee, _, NoSugar) => {
- let def_map = def_map.borrow();
- match def_map.get().find(&callee.id) {
+ ExprCall(callee, _) => {
+ match v.def_map.borrow().find(&callee.id) {
Some(&DefStruct(..)) => {} // OK.
Some(&DefVariant(..)) => {} // OK.
_ => {
- sess.span_err(
- e.span,
+ v.tcx.sess.span_err(e.span,
"function calls in constants are limited to \
struct and enum constructors");
}
}
}
+ ExprVstore(_, ExprVstoreMutSlice) |
ExprVstore(_, ExprVstoreSlice) |
- ExprVec(_, MutImmutable) |
+ ExprVec(_) |
ExprAddrOf(MutImmutable, _) |
ExprParen(..) |
ExprField(..) |
ExprRepeat(..) |
ExprStruct(..) => { }
ExprAddrOf(..) => {
- sess.span_err(
- e.span,
+ v.tcx.sess.span_err(e.span,
"references in constants may only refer to \
immutable values");
},
ExprVstore(_, ExprVstoreUniq) => {
- sess.span_err(e.span, "cannot allocate vectors in constant expressions")
+ v.tcx.sess.span_err(e.span, "cannot allocate vectors in constant expressions")
},
_ => {
- sess.span_err(e.span,
- "constant contains unimplemented expression type");
+ v.tcx.sess.span_err(e.span,
+ "constant contains unimplemented expression type");
return;
}
}
struct CheckItemRecursionVisitor<'a> {
root_it: &'a Item,
- sess: Session,
- ast_map: ast_map::Map,
+ sess: &'a Session,
+ ast_map: &'a ast_map::Map,
def_map: resolve::DefMap,
- idstack: ~[NodeId]
-}
+ idstack: Vec<NodeId> }
// 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,
- ast_map: ast_map::Map,
- def_map: resolve::DefMap,
- it: &Item) {
+pub fn check_item_recursion<'a>(sess: &'a Session,
+ ast_map: &'a ast_map::Map,
+ def_map: resolve::DefMap,
+ it: &'a Item) {
let mut visitor = CheckItemRecursionVisitor {
root_it: it,
sess: sess,
ast_map: ast_map,
def_map: def_map,
- idstack: ~[]
+ idstack: Vec::new()
};
visitor.visit_item(it, ());
}
fn visit_expr(&mut self, e: &Expr, _: ()) {
match e.node {
ExprPath(..) => {
- let def_map = self.def_map.borrow();
- match def_map.get().find(&e.id) {
+ match self.def_map.borrow().find(&e.id) {
Some(&DefStatic(def_id, _)) if
ast_util::is_local(def_id) => {
- match self.ast_map.get(def_id.node) {
- ast_map::NodeItem(it, _) => {
- self.visit_item(it, ());
- }
- _ => fail!("const not bound to an item")
- }
+ self.visit_item(self.ast_map.expect_item(def_id.node), ());
}
_ => ()
}