use std::rc::Rc;
use std::str;
use std::uint;
+use syntax::ast;
use syntax::ast::*;
use syntax::codemap::{BytePos, original_sp, Span};
use syntax::parse::token::special_idents;
}
}
-#[deriving(PartialEq)]
+#[deriving(PartialEq, Show)]
enum LiveNodeKind {
FreeVarNode(Span),
ExprNode(Span),
b: &'v Block, s: Span, n: NodeId) {
visit_fn(self, fk, fd, b, s, n);
}
- fn visit_local(&mut self, l: &Local) { visit_local(self, l); }
+ fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
fn visit_expr(&mut self, ex: &Expr) { visit_expr(self, ex); }
fn visit_arm(&mut self, a: &Arm) { visit_arm(self, a); }
}
var_nid: NodeId
}
+#[deriving(Show)]
struct LocalInfo {
id: NodeId,
ident: Ident
}
+#[deriving(Show)]
enum VarKind {
Arg(NodeId, Ident),
Local(LocalInfo),
ImplicitRet => {}
}
- debug!("{} is {:?}", v.to_string(), vk);
+ debug!("{} is {}", v.to_string(), vk);
v
}
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, n: NodeId) {
check_fn(self, fk, fd, b, s, n);
}
- fn visit_local(&mut self, l: &Local) {
+ fn visit_local(&mut self, l: &ast::Local) {
check_local(self, l);
}
fn visit_expr(&mut self, ex: &Expr) {
lsets.warn_about_unused_args(decl, entry_ln);
}
-fn visit_local(ir: &mut IrMaps, local: &Local) {
+fn visit_local(ir: &mut IrMaps, local: &ast::Local) {
pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
debug!("adding local variable {}", p_id);
let name = path1.node;
fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
for pat in arm.pats.iter() {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
- debug!("adding local variable {} from match with bm {:?}",
+ debug!("adding local variable {} from match with bm {}",
p_id, bm);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
// live nodes required for uses or definitions of variables:
ExprPath(_) => {
let def = ir.tcx.def_map.borrow().get_copy(&expr.id);
- debug!("expr {}: path that leads to {:?}", expr.id, def);
+ debug!("expr {}: path that leads to {}", expr.id, def);
match def {
DefLocal(..) => ir.add_live_node_for_node(expr.id, ExprNode(expr.span)),
_ => {}
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
visit::walk_expr(ir, expr);
}
+ ExprIfLet(..) => {
+ ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
+ }
+ ExprWhileLet(..) => {
+ ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
+ }
ExprForLoop(ref pat, _, _, _) => {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
- debug!("adding local variable {} from for loop with bm {:?}",
+ debug!("adding local variable {} from for loop with bm {}",
p_id, bm);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
// otherwise, live nodes are not required:
ExprIndex(..) | ExprField(..) | ExprTupField(..) | ExprVec(..) |
- ExprCall(..) | ExprMethodCall(..) | ExprTup(..) |
+ ExprCall(..) | ExprMethodCall(..) | ExprTup(..) | ExprSlice(..) |
ExprBinary(..) | ExprAddrOf(..) |
ExprCast(..) | ExprUnary(..) | ExprBreak(_) |
ExprAgain(_) | ExprLit(_) | ExprRet(..) | ExprBlock(..) |
let mut wr = io::MemWriter::new();
{
let wr = &mut wr as &mut io::Writer;
- write!(wr, "[ln({}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
+ write!(wr, "[ln({}) of kind {} reads", ln.get(), self.ir.lnk(ln));
self.write_vars(wr, ln, |idx| self.users.get(idx).reader);
write!(wr, " writes");
self.write_vars(wr, ln, |idx| self.users.get(idx).writer);
}
}
- fn propagate_through_local(&mut self, local: &Local, succ: LiveNode)
+ fn propagate_through_local(&mut self, local: &ast::Local, succ: LiveNode)
-> LiveNode {
// Note: we mark the variable as defined regardless of whether
// there is an initializer. Initially I had thought to only mark
self.propagate_through_expr(&**cond, ln)
}
+ ExprIfLet(..) => {
+ self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
+ }
+
ExprWhile(ref cond, ref blk, _) => {
self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
}
+ ExprWhileLet(..) => {
+ self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
+ }
+
ExprForLoop(ref pat, ref head, ref blk, _) => {
let ln = self.propagate_through_loop(expr, ForLoop(&**pat), &**blk, succ);
self.propagate_through_expr(&**head, ln)
self.propagate_through_loop(expr, LoopLoop, &**blk, succ)
}
- ExprMatch(ref e, ref arms) => {
+ ExprMatch(ref e, ref arms, _) => {
//
// (e)
// |
self.propagate_through_expr(&**l, r_succ)
}
+ ExprSlice(ref e1, ref e2, ref e3, _) => {
+ let succ = e3.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
+ let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
+ self.propagate_through_expr(&**e1, succ)
+ }
+
ExprAddrOf(_, ref e) |
ExprCast(ref e, _) |
ExprUnary(_, ref e) |
// _______________________________________________________________________
// Checking for error conditions
-fn check_local(this: &mut Liveness, local: &Local) {
+fn check_local(this: &mut Liveness, local: &ast::Local) {
match local.init {
Some(_) => {
this.warn_about_unused_or_dead_vars_in_pat(&*local.pat);
this.pat_bindings(&**pat, |this, ln, var, sp, id| {
this.warn_about_unused(sp, id, ln, var);
});
+
+ visit::walk_expr(this, expr);
}
// no correctness conditions related to liveness
ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
ExprTupField(..) | ExprVec(..) | ExprTup(..) | ExprBinary(..) |
ExprCast(..) | ExprUnary(..) | ExprRet(..) | ExprBreak(..) |
- ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
+ ExprAgain(..) | ExprLit(_) | ExprBlock(..) | ExprSlice(..) |
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprUnboxedFn(..) |
ExprPath(..) | ExprBox(..) => {
visit::walk_expr(this, expr);
}
+ ExprIfLet(..) => {
+ this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
+ }
+ ExprWhileLet(..) => {
+ this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
+ }
}
}
};
if is_assigned {
- self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLE, id, sp,
+ self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
format!("variable `{}` is assigned to, but never used",
*name));
} else {
- self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLE, id, sp,
+ self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
format!("unused variable: `{}`", *name));
}
}
if self.live_on_exit(ln, var).is_none() {
let r = self.should_warn(var);
for name in r.iter() {
- self.ir.tcx.sess.add_lint(lint::builtin::DEAD_ASSIGNMENT, id, sp,
+ self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
format!("value assigned to `{}` is never read", *name));
}
}