Upgrade Rust to rustc 1.5.0-nightly (cff041170 2015-09-17)

LintPass was split and ExprParen was removed from the HIR

Fixes #338
This commit is contained in:
Manish Goregaokar 2015-09-19 08:23:04 +05:30
parent 862c195fa1
commit f4da7d09d2
29 changed files with 238 additions and 180 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.14"
version = "0.0.15"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",

View File

@ -29,15 +29,17 @@ impl LintPass for ApproxConstant {
fn get_lints(&self) -> LintArray {
lint_array!(APPROX_CONSTANT)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for ApproxConstant {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let &ExprLit(ref lit) = &e.node {
check_lit(cx, lit, e);
}
}
}
fn check_lit(cx: &Context, lit: &Lit, e: &Expr) {
fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) {
match lit.node {
LitFloat(ref str, TyF32) => check_known_consts(cx, e, str, "f32"),
LitFloat(ref str, TyF64) => check_known_consts(cx, e, str, "f64"),
@ -47,7 +49,7 @@ fn check_lit(cx: &Context, lit: &Lit, e: &Expr) {
}
}
fn check_known_consts(cx: &Context, e: &Expr, str: &str, module: &str) {
fn check_known_consts(cx: &LateContext, e: &Expr, str: &str, module: &str) {
if let Ok(value) = str.parse::<f64>() {
for &(constant, name) in KNOWN_CONSTS {
if !within_epsilon(constant, value) { continue; }

View File

@ -19,20 +19,22 @@ impl LintPass for AttrPass {
fn get_lints(&self) -> LintArray {
lint_array!(INLINE_ALWAYS)
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
impl LateLintPass for AttrPass {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if is_relevant_item(item) {
check_attrs(cx, item.span, &item.ident, &item.attrs)
}
}
fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if is_relevant_impl(item) {
check_attrs(cx, item.span, &item.ident, &item.attrs)
}
}
fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if is_relevant_trait(item) {
check_attrs(cx, item.span, &item.ident, &item.attrs)
}
@ -75,8 +77,7 @@ fn is_relevant_block(block: &Block) -> bool {
fn is_relevant_expr(expr: &Expr) -> bool {
match expr.node {
ExprBlock(ref block) => is_relevant_block(block),
ExprRet(Some(ref e)) | ExprParen(ref e) =>
is_relevant_expr(e),
ExprRet(Some(ref e)) => is_relevant_expr(e),
ExprRet(None) | ExprBreak(_) => false,
ExprCall(ref path_expr, _) => {
if let ExprPath(_, ref path) = path_expr.node {
@ -87,7 +88,7 @@ fn is_relevant_expr(expr: &Expr) -> bool {
}
}
fn check_attrs(cx: &Context, span: Span, ident: &Ident,
fn check_attrs(cx: &LateContext, span: Span, ident: &Ident,
attrs: &[Attribute]) {
if in_macro(cx, span) { return; }

View File

@ -54,8 +54,10 @@ impl LintPass for BitMask {
fn get_lints(&self) -> LintArray {
lint_array!(BAD_BIT_MASK, INEFFECTIVE_BIT_MASK)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for BitMask {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
if is_comparison_binop(cmp.node) {
fetch_int_literal(cx, right).map_or_else(||
@ -82,9 +84,8 @@ fn invert_cmp(cmp : BinOp_) -> BinOp_ {
}
fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) {
fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) {
match bit_op.node {
ExprParen(ref subexp) => check_compare(cx, subexp, cmp_op, cmp_value, span),
ExprBinary(ref op, ref left, ref right) => {
if op.node != BiBitAnd && op.node != BiBitOr { return; }
fetch_int_literal(cx, right).or_else(|| fetch_int_literal(
@ -95,7 +96,7 @@ fn check_compare(cx: &Context, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, sp
}
}
fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_,
fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_,
mask_value: u64, cmp_value: u64, span: &Span) {
match cmp_op {
BiEq | BiNe => match bit_op {
@ -163,7 +164,7 @@ fn check_bit_mask(cx: &Context, bit_op: BinOp_, cmp_op: BinOp_,
}
}
fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) {
fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) {
if c.is_power_of_two() && m < c {
span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!(
"ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
@ -171,7 +172,7 @@ fn check_ineffective_lt(cx: &Context, span: Span, m: u64, c: u64, op: &str) {
}
}
fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) {
fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) {
if (c + 1).is_power_of_two() && m <= c {
span_lint(cx, INEFFECTIVE_BIT_MASK, span, &format!(
"ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
@ -179,7 +180,7 @@ fn check_ineffective_gt(cx: &Context, span: Span, m: u64, c: u64, op: &str) {
}
}
fn fetch_int_literal(cx: &Context, lit : &Expr) -> Option<u64> {
fn fetch_int_literal(cx: &LateContext, lit : &Expr) -> Option<u64> {
match lit.node {
ExprLit(ref lit_ptr) => {
if let &LitInt(value, _) = &lit_ptr.node {

View File

@ -32,15 +32,17 @@ impl LintPass for CollapsibleIf {
fn get_lints(&self) -> LintArray {
lint_array!(COLLAPSIBLE_IF)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for CollapsibleIf {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if !in_macro(cx, expr.span) {
check_if(cx, expr)
}
}
}
fn check_if(cx: &Context, e: &Expr) {
fn check_if(cx: &LateContext, e: &Expr) {
if let ExprIf(ref check, ref then, None) = e.node {
if let Some(&Expr{ node: ExprIf(ref check_inner, ref content, None), span: sp, ..}) =
single_stmt_of_block(then) {
@ -63,7 +65,7 @@ fn requires_brackets(e: &Expr) -> bool {
}
}
fn check_to_string(cx: &Context, e: &Expr) -> String {
fn check_to_string(cx: &LateContext, e: &Expr) -> String {
if requires_brackets(e) {
format!("({})", snippet(cx, e.span, ".."))
} else {

View File

@ -1,6 +1,6 @@
#![allow(cast_possible_truncation)]
use rustc::lint::Context;
use rustc::lint::LateContext;
use rustc::middle::const_eval::lookup_const_by_id;
use rustc::middle::def::PathResolution;
use rustc::middle::def::Def::*;
@ -287,27 +287,26 @@ fn sub_int(l: u64, lty: LitIntType, r: u64, rty: LitIntType, neg: bool) ->
}
pub fn constant(lcx: &Context, e: &Expr) -> Option<(Constant, bool)> {
let mut cx = ConstEvalContext { lcx: Some(lcx), needed_resolution: false };
pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> {
let mut cx = ConstEvalLateContext { lcx: Some(lcx), needed_resolution: false };
cx.expr(e).map(|cst| (cst, cx.needed_resolution))
}
pub fn constant_simple(e: &Expr) -> Option<Constant> {
let mut cx = ConstEvalContext { lcx: None, needed_resolution: false };
let mut cx = ConstEvalLateContext { lcx: None, needed_resolution: false };
cx.expr(e)
}
struct ConstEvalContext<'c, 'cc: 'c> {
lcx: Option<&'c Context<'c, 'cc>>,
struct ConstEvalLateContext<'c, 'cc: 'c> {
lcx: Option<&'c LateContext<'c, 'cc>>,
needed_resolution: bool
}
impl<'c, 'cc> ConstEvalContext<'c, 'cc> {
impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
/// simple constant folding: Insert an expression, get a constant or none.
fn expr(&mut self, e: &Expr) -> Option<Constant> {
match e.node {
ExprParen(ref inner) => self.expr(inner),
ExprPath(_, _) => self.fetch_path(e),
ExprBlock(ref block) => self.block(block),
ExprIf(ref cond, ref then, ref otherwise) =>

View File

@ -19,8 +19,10 @@ impl LintPass for EqOp {
fn get_lints(&self) -> LintArray {
lint_array!(EQ_OP)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for EqOp {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprBinary(ref op, ref left, ref right) = e.node {
if is_cmp_or_bit(op) && is_exp_equal(cx, left, right) {
span_lint(cx, EQ_OP, e.span, &format!(
@ -31,7 +33,7 @@ impl LintPass for EqOp {
}
}
pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool {
pub fn is_exp_equal(cx: &LateContext, left : &Expr, right : &Expr) -> bool {
if let (Some(l), Some(r)) = (constant(cx, left), constant(cx, right)) {
if l == r {
return true;
@ -42,8 +44,6 @@ pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool {
&ExprField(ref rfexp, ref rfident)) =>
lfident.node == rfident.node && is_exp_equal(cx, lfexp, rfexp),
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
(&ExprParen(ref lparen), _) => is_exp_equal(cx, lparen, right),
(_, &ExprParen(ref rparen)) => is_exp_equal(cx, left, rparen),
(&ExprPath(ref lqself, ref lsubpath),
&ExprPath(ref rqself, ref rsubpath)) =>
both(lqself, rqself, is_qself_equal) &&
@ -57,7 +57,7 @@ pub fn is_exp_equal(cx: &Context, left : &Expr, right : &Expr) -> bool {
}
}
fn is_exps_equal(cx: &Context, left : &[P<Expr>], right : &[P<Expr>]) -> bool {
fn is_exps_equal(cx: &LateContext, left : &[P<Expr>], right : &[P<Expr>]) -> bool {
over(left, right, |l, r| is_exp_equal(cx, l, r))
}

View File

@ -16,8 +16,10 @@ impl LintPass for EtaPass {
fn get_lints(&self) -> LintArray {
lint_array!(REDUNDANT_CLOSURE)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for EtaPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
match expr.node {
ExprCall(_, ref args) |
ExprMethodCall(_, _, ref args) => {
@ -30,11 +32,11 @@ impl LintPass for EtaPass {
}
}
fn is_adjusted(cx: &Context, e: &Expr) -> bool {
fn is_adjusted(cx: &LateContext, e: &Expr) -> bool {
cx.tcx.tables.borrow().adjustments.get(&e.id).is_some()
}
fn check_closure(cx: &Context, expr: &Expr) {
fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, ref blk) = expr.node {
if !blk.stmts.is_empty() {
// || {foo(); bar()}; can't be reduced here

View File

@ -16,8 +16,10 @@ impl LintPass for IdentityOp {
fn get_lints(&self) -> LintArray {
lint_array!(IDENTITY_OP)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for IdentityOp {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if in_macro(cx, e.span) { return; }
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
match cmp.node {
@ -44,7 +46,7 @@ impl LintPass for IdentityOp {
}
fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) {
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
if let Some(ConstantInt(v, ty)) = constant_simple(e) {
if match m {
0 => v == 0,

View File

@ -24,8 +24,10 @@ impl LintPass for LenZero {
fn get_lints(&self) -> LintArray {
lint_array!(LEN_ZERO, LEN_WITHOUT_IS_EMPTY)
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
impl LateLintPass for LenZero {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
match item.node {
ItemTrait(_, _, _, ref trait_items) =>
check_trait_items(cx, item, trait_items),
@ -35,7 +37,7 @@ impl LintPass for LenZero {
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(Spanned{node: cmp, ..}, ref left, ref right) =
expr.node {
match cmp {
@ -47,7 +49,7 @@ impl LintPass for LenZero {
}
}
fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) {
fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[P<TraitItem>]) {
fn is_named_self(item: &TraitItem, name: &str) -> bool {
item.ident.name == name && if let MethodTraitItem(ref sig, _) =
item.node { is_self_sig(sig) } else { false }
@ -66,7 +68,7 @@ fn check_trait_items(cx: &Context, item: &Item, trait_items: &[P<TraitItem>]) {
}
}
fn check_impl_items(cx: &Context, item: &Item, impl_items: &[P<ImplItem>]) {
fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[P<ImplItem>]) {
fn is_named_self(item: &ImplItem, name: &str) -> bool {
item.ident.name == name && if let MethodImplItem(ref sig, _) =
item.node { is_self_sig(sig) } else { false }
@ -92,7 +94,7 @@ fn is_self_sig(sig: &MethodSig) -> bool {
false } else { sig.decl.inputs.len() == 1 }
}
fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) {
fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, left) {
if name == "is_empty" { return; }
@ -106,7 +108,7 @@ fn check_cmp(cx: &Context, span: Span, left: &Expr, right: &Expr, op: &str) {
}
}
fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent,
fn check_len_zero(cx: &LateContext, span: Span, method: &SpannedIdent,
args: &[P<Expr>], lit: &Lit, op: &str) {
if let Spanned{node: LitInt(0, _), ..} = *lit {
if method.node.name == "len" && args.len() == 1 &&
@ -119,9 +121,9 @@ fn check_len_zero(cx: &Context, span: Span, method: &SpannedIdent,
}
/// check if this type has an is_empty method
fn has_is_empty(cx: &Context, expr: &Expr) -> bool {
fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
/// get a ImplOrTraitItem and return true if it matches is_empty(self)
fn is_is_empty(cx: &Context, id: &ImplOrTraitItemId) -> bool {
fn is_is_empty(cx: &LateContext, id: &ImplOrTraitItemId) -> bool {
if let &MethodTraitItemId(def_id) = id {
if let ty::MethodTraitItem(ref method) =
cx.tcx.impl_or_trait_item(def_id) {
@ -132,7 +134,7 @@ fn has_is_empty(cx: &Context, expr: &Expr) -> bool {
}
/// check the inherent impl's items for an is_empty(self) method
fn has_is_empty_impl(cx: &Context, id: &DefId) -> bool {
fn has_is_empty_impl(cx: &LateContext, id: &DefId) -> bool {
let impl_items = cx.tcx.impl_items.borrow();
cx.tcx.inherent_impls.borrow().get(id).map_or(false,
|ids| ids.iter().any(|iid| impl_items.get(iid).map_or(false,

View File

@ -18,7 +18,6 @@ extern crate collections;
extern crate unicode_normalization;
use rustc::plugin::Registry;
use rustc::lint::LintPassObject;
#[macro_use]
pub mod utils;
@ -54,39 +53,39 @@ mod reexport {
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box types::TypePass as LintPassObject);
reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject);
reg.register_lint_pass(box misc::CmpNan as LintPassObject);
reg.register_lint_pass(box eq_op::EqOp as LintPassObject);
reg.register_lint_pass(box bit_mask::BitMask as LintPassObject);
reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject);
reg.register_lint_pass(box needless_bool::NeedlessBool as LintPassObject);
reg.register_lint_pass(box approx_const::ApproxConstant as LintPassObject);
reg.register_lint_pass(box misc::FloatCmp as LintPassObject);
reg.register_lint_pass(box precedence::Precedence as LintPassObject);
reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject);
reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject);
reg.register_lint_pass(box mut_mut::MutMut as LintPassObject);
reg.register_lint_pass(box len_zero::LenZero as LintPassObject);
reg.register_lint_pass(box misc::CmpOwned as LintPassObject);
reg.register_lint_pass(box attrs::AttrPass as LintPassObject);
reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject);
reg.register_lint_pass(box misc::ModuloOne as LintPassObject);
reg.register_lint_pass(box unicode::Unicode as LintPassObject);
reg.register_lint_pass(box strings::StringAdd as LintPassObject);
reg.register_lint_pass(box returns::ReturnPass as LintPassObject);
reg.register_lint_pass(box methods::MethodsPass as LintPassObject);
reg.register_lint_pass(box shadow::ShadowPass as LintPassObject);
reg.register_lint_pass(box types::LetPass as LintPassObject);
reg.register_lint_pass(box types::UnitCmp as LintPassObject);
reg.register_lint_pass(box loops::LoopsPass as LintPassObject);
reg.register_lint_pass(box lifetimes::LifetimePass as LintPassObject);
reg.register_lint_pass(box ranges::StepByZero as LintPassObject);
reg.register_lint_pass(box types::CastPass as LintPassObject);
reg.register_lint_pass(box types::TypeComplexityPass as LintPassObject);
reg.register_lint_pass(box matches::MatchPass as LintPassObject);
reg.register_lint_pass(box misc::PatternPass as LintPassObject);
reg.register_lint_pass(box minmax::MinMaxPass as LintPassObject);
reg.register_late_lint_pass(box types::TypePass);
reg.register_late_lint_pass(box misc::TopLevelRefPass);
reg.register_late_lint_pass(box misc::CmpNan);
reg.register_late_lint_pass(box eq_op::EqOp);
reg.register_late_lint_pass(box bit_mask::BitMask);
reg.register_late_lint_pass(box ptr_arg::PtrArg);
reg.register_late_lint_pass(box needless_bool::NeedlessBool);
reg.register_late_lint_pass(box approx_const::ApproxConstant);
reg.register_late_lint_pass(box misc::FloatCmp);
reg.register_early_lint_pass(box precedence::Precedence);
reg.register_late_lint_pass(box eta_reduction::EtaPass);
reg.register_late_lint_pass(box identity_op::IdentityOp);
reg.register_late_lint_pass(box mut_mut::MutMut);
reg.register_late_lint_pass(box len_zero::LenZero);
reg.register_late_lint_pass(box misc::CmpOwned);
reg.register_late_lint_pass(box attrs::AttrPass);
reg.register_late_lint_pass(box collapsible_if::CollapsibleIf);
reg.register_late_lint_pass(box misc::ModuloOne);
reg.register_late_lint_pass(box unicode::Unicode);
reg.register_late_lint_pass(box strings::StringAdd);
reg.register_late_lint_pass(box returns::ReturnPass);
reg.register_late_lint_pass(box methods::MethodsPass);
reg.register_late_lint_pass(box shadow::ShadowPass);
reg.register_late_lint_pass(box types::LetPass);
reg.register_late_lint_pass(box types::UnitCmp);
reg.register_late_lint_pass(box loops::LoopsPass);
reg.register_late_lint_pass(box lifetimes::LifetimePass);
reg.register_late_lint_pass(box ranges::StepByZero);
reg.register_late_lint_pass(box types::CastPass);
reg.register_late_lint_pass(box types::TypeComplexityPass);
reg.register_late_lint_pass(box matches::MatchPass);
reg.register_late_lint_pass(box misc::PatternPass);
reg.register_late_lint_pass(box minmax::MinMaxPass);
reg.register_lint_group("clippy_pedantic", vec![
methods::OPTION_UNWRAP_USED,

View File

@ -18,21 +18,23 @@ impl LintPass for LifetimePass {
fn get_lints(&self) -> LintArray {
lint_array!(NEEDLESS_LIFETIMES)
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
impl LateLintPass for LifetimePass {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node {
check_fn_inner(cx, decl, None, &generics, item.span);
}
}
fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if let MethodImplItem(ref sig, _) = item.node {
check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self),
&sig.generics, item.span);
}
}
fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if let MethodTraitItem(ref sig, _) = item.node {
check_fn_inner(cx, &sig.decl, Some(&sig.explicit_self),
&sig.generics, item.span);
@ -49,7 +51,7 @@ enum RefLt {
}
use self::RefLt::*;
fn check_fn_inner(cx: &Context, decl: &FnDecl, slf: Option<&ExplicitSelf>,
fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>,
generics: &Generics, span: Span) {
if in_external_macro(cx, span) || has_where_lifetimes(&generics.where_clause) {
return;

View File

@ -43,8 +43,10 @@ impl LintPass for LoopsPass {
lint_array!(NEEDLESS_RANGE_LOOP, EXPLICIT_ITER_LOOP, ITER_NEXT_LOOP,
WHILE_LET_LOOP, UNUSED_COLLECT, REVERSE_RANGE_LOOP, EXPLICIT_COUNTER_LOOP)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for LoopsPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let Some((pat, arg, body)) = recover_for_loop(expr) {
// check for looping over a range and then indexing a sequence with it
// -> the iteratee must be a range literal
@ -186,7 +188,7 @@ impl LintPass for LoopsPass {
}
}
fn check_stmt(&mut self, cx: &Context, stmt: &Stmt) {
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
if let StmtSemi(ref expr, _) = stmt.node {
if let ExprMethodCall(ref method, _, ref args) = expr.node {
if args.len() == 1 && method.node.name == "collect" &&
@ -225,7 +227,7 @@ fn recover_for_loop(expr: &Expr) -> Option<(&Pat, &Expr, &Expr)> {
}
struct VarVisitor<'v, 't: 'v> {
cx: &'v Context<'v, 't>, // context reference
cx: &'v LateContext<'v, 't>, // context reference
var: Name, // var name to look for as index
indexed: HashSet<Name>, // indexed variables
nonindex: bool, // has the var been used otherwise?
@ -258,7 +260,7 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
/// Return true if the type of expr is one that provides IntoIterator impls
/// for &T and &mut T, such as Vec.
fn is_ref_iterable_type(cx: &Context, e: &Expr) -> bool {
fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
// no walk_ptrs_ty: calling iter() on a reference can make sense because it
// will allow further borrows afterwards
let ty = cx.tcx.expr_ty(e);
@ -320,7 +322,7 @@ enum VarState {
// Scan a for loop for variables that are incremented exactly once.
struct IncrementVisitor<'v, 't: 'v> {
cx: &'v Context<'v, 't>, // context reference
cx: &'v LateContext<'v, 't>, // context reference
states: HashMap<NodeId, VarState>, // incremented variables
depth: u32, // depth of conditional expressions
done: bool
@ -376,7 +378,7 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> {
// Check whether a variable is initialized to zero at the start of a loop.
struct InitializeVisitor<'v, 't: 'v> {
cx: &'v Context<'v, 't>, // context reference
cx: &'v LateContext<'v, 't>, // context reference
end_expr: &'v Expr, // the for loop. Stop scanning here.
var_id: NodeId,
state: VarState,
@ -454,7 +456,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
}
}
fn var_def_id(cx: &Context, expr: &Expr) -> Option<NodeId> {
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) {
if let DefLocal(node_id) = path_res.base_def {
return Some(node_id)

View File

@ -17,8 +17,10 @@ impl LintPass for MatchPass {
fn get_lints(&self) -> LintArray {
lint_array!(SINGLE_MATCH, MATCH_REF_PATS)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for MatchPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node {
// check preconditions for SINGLE_MATCH
// only two arms

View File

@ -36,8 +36,10 @@ impl LintPass for MethodsPass {
lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING,
SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for MethodsPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprMethodCall(ref ident, _, ref args) = expr.node {
let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0]));
if ident.node.name == "unwrap" {
@ -71,7 +73,7 @@ impl LintPass for MethodsPass {
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node {
for implitem in items {
let name = implitem.ident.name;
@ -229,7 +231,7 @@ fn is_bool(ty: &Ty) -> bool {
false
}
fn is_copy(cx: &Context, ast_ty: &Ty, item: &Item) -> bool {
fn is_copy(cx: &LateContext, ast_ty: &Ty, item: &Item) -> bool {
match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
None => false,
Some(ty) => {

View File

@ -1,4 +1,4 @@
use rustc::lint::{Context, LintPass, LintArray};
use rustc::lint::*;
use rustc_front::hir::*;
use syntax::ptr::P;
use std::cmp::PartialOrd;
@ -19,8 +19,10 @@ impl LintPass for MinMaxPass {
fn get_lints(&self) -> LintArray {
lint_array!(MIN_MAX)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for MinMaxPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let Some((outer_max, outer_c, oe)) = min_max(expr) {
if let Some((inner_max, inner_c, _)) = min_max(oe) {
if outer_max == inner_max { return; }

View File

@ -21,8 +21,10 @@ impl LintPass for TopLevelRefPass {
fn get_lints(&self) -> LintArray {
lint_array!(TOPLEVEL_REF_ARG)
}
}
fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
impl LateLintPass for TopLevelRefPass {
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
if let FnKind::Closure = k {
// Does not apply to closures
return
@ -49,8 +51,10 @@ impl LintPass for CmpNan {
fn get_lints(&self) -> LintArray {
lint_array!(CMP_NAN)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for CmpNan {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
if is_comparison_binop(cmp.node) {
if let &ExprPath(_, ref path) = &left.node {
@ -64,7 +68,7 @@ impl LintPass for CmpNan {
}
}
fn check_nan(cx: &Context, path: &Path, span: Span) {
fn check_nan(cx: &LateContext, path: &Path, span: Span) {
path.segments.last().map(|seg| if seg.identifier.name == "NAN" {
span_lint(cx, CMP_NAN, span,
"doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead");
@ -83,8 +87,10 @@ impl LintPass for FloatCmp {
fn get_lints(&self) -> LintArray {
lint_array!(FLOAT_CMP)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for FloatCmp {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
let op = cmp.node;
if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
@ -109,7 +115,7 @@ impl LintPass for FloatCmp {
}
}
fn is_float(cx: &Context, expr: &Expr) -> bool {
fn is_float(cx: &LateContext, expr: &Expr) -> bool {
if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty {
true
} else {
@ -127,8 +133,10 @@ impl LintPass for CmpOwned {
fn get_lints(&self) -> LintArray {
lint_array!(CMP_OWNED)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for CmpOwned {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
if is_comparison_binop(cmp.node) {
check_to_owned(cx, left, right.span);
@ -138,7 +146,7 @@ impl LintPass for CmpOwned {
}
}
fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) {
fn check_to_owned(cx: &LateContext, expr: &Expr, other_span: Span) {
match expr.node {
ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => {
let name = ident.name;
@ -165,7 +173,7 @@ fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) {
}
}
fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool {
fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool {
args.len() == 1 && if let ty::TyStr =
walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false }
}
@ -179,8 +187,10 @@ impl LintPass for ModuloOne {
fn get_lints(&self) -> LintArray {
lint_array!(MODULO_ONE)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for ModuloOne {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref cmp, _, ref right) = expr.node {
if let &Spanned {node: BinOp_::BiRem, ..} = cmp {
if is_integer_literal(right, 1) {
@ -200,8 +210,10 @@ impl LintPass for PatternPass {
fn get_lints(&self) -> LintArray {
lint_array!(REDUNDANT_PATTERN)
}
}
fn check_pat(&mut self, cx: &Context, pat: &Pat) {
impl LateLintPass for PatternPass {
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatIdent(_, ref ident, Some(ref right)) = pat.node {
if right.node == PatWild(PatWildSingle) {
cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!(

View File

@ -15,18 +15,20 @@ impl LintPass for MutMut {
fn get_lints(&self) -> LintArray {
lint_array!(MUT_MUT)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for MutMut {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
check_expr_mut(cx, expr)
}
fn check_ty(&mut self, cx: &Context, ty: &Ty) {
fn check_ty(&mut self, cx: &LateContext, ty: &Ty) {
unwrap_mut(ty).and_then(unwrap_mut).map_or((), |_| span_lint(cx, MUT_MUT,
ty.span, "generally you want to avoid `&mut &mut _` if possible"))
}
}
fn check_expr_mut(cx: &Context, expr: &Expr) {
fn check_expr_mut(cx: &LateContext, expr: &Expr) {
if in_external_macro(cx, expr.span) { return; }
fn unwrap_addr(expr : &Expr) -> Option<&Expr> {

View File

@ -23,8 +23,10 @@ impl LintPass for NeedlessBool {
fn get_lints(&self) -> LintArray {
lint_array!(NEEDLESS_BOOL)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node {
match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
(Some(true), Some(true)) => {

View File

@ -1,7 +1,6 @@
use rustc::lint::*;
use rustc_front::hir::*;
use syntax::codemap::Spanned;
use syntax::ast::Lit_::*;
use syntax::ast::*;
use utils::span_lint;
declare_lint!(pub PRECEDENCE, Warn,
@ -15,8 +14,10 @@ impl LintPass for Precedence {
fn get_lints(&self) -> LintArray {
lint_array!(PRECEDENCE)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl EarlyLintPass for Precedence {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if let ExprBinary(Spanned { node: op, ..}, ref left, ref right) = expr.node {
if is_bit_op(op) && (is_arith_expr(left) || is_arith_expr(right)) {
span_lint(cx, PRECEDENCE, expr.span,

View File

@ -23,27 +23,29 @@ impl LintPass for PtrArg {
fn get_lints(&self) -> LintArray {
lint_array!(PTR_ARG)
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
impl LateLintPass for PtrArg {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let &ItemFn(ref decl, _, _, _, _, _) = &item.node {
check_fn(cx, decl);
}
}
fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if let &MethodImplItem(ref sig, _) = &item.node {
check_fn(cx, &sig.decl);
}
}
fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if let &MethodTraitItem(ref sig, _) = &item.node {
check_fn(cx, &sig.decl);
}
}
}
fn check_fn(cx: &Context, decl: &FnDecl) {
fn check_fn(cx: &LateContext, decl: &FnDecl) {
for arg in &decl.inputs {
if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) {
if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty {

View File

@ -1,4 +1,4 @@
use rustc::lint::{Context, LintArray, LintPass};
use rustc::lint::*;
use rustc_front::hir::*;
use syntax::codemap::Spanned;
use utils::{match_type, is_integer_literal};
@ -15,8 +15,10 @@ impl LintPass for StepByZero {
fn get_lints(&self) -> LintArray {
lint_array!(RANGE_STEP_BY_ZERO)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for StepByZero {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprMethodCall(Spanned { node: ref ident, .. }, _,
ref args) = expr.node {
// Only warn on literal ranges.
@ -30,7 +32,7 @@ impl LintPass for StepByZero {
}
}
fn is_range(cx: &Context, expr: &Expr) -> bool {
fn is_range(cx: &LateContext, expr: &Expr) -> bool {
// No need for walk_ptrs_ty here because step_by moves self, so it
// can't be called on a borrowed range.
let ty = cx.tcx.expr_ty(expr);

View File

@ -17,7 +17,7 @@ pub struct ReturnPass;
impl ReturnPass {
// Check the final stmt or expr in a block for unnecessary return.
fn check_block_return(&mut self, cx: &Context, block: &Block) {
fn check_block_return(&mut self, cx: &LateContext, block: &Block) {
if let Some(ref expr) = block.expr {
self.check_final_expr(cx, expr);
} else if let Some(stmt) = block.stmts.last() {
@ -30,7 +30,7 @@ impl ReturnPass {
}
// Check a the final expression in a block if it's a return.
fn check_final_expr(&mut self, cx: &Context, expr: &Expr) {
fn check_final_expr(&mut self, cx: &LateContext, expr: &Expr) {
match expr.node {
// simple return is always "bad"
ExprRet(Some(ref inner)) => {
@ -57,7 +57,7 @@ impl ReturnPass {
}
}
fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) {
fn emit_return_lint(&mut self, cx: &LateContext, spans: (Span, Span)) {
if in_external_macro(cx, spans.1) {return;}
span_lint(cx, NEEDLESS_RETURN, spans.0, &format!(
"unneeded return statement. Consider using `{}` \
@ -66,7 +66,7 @@ impl ReturnPass {
}
// Check for "let x = EXPR; x"
fn check_let_return(&mut self, cx: &Context, block: &Block) {
fn check_let_return(&mut self, cx: &LateContext, block: &Block) {
// we need both a let-binding stmt and an expr
if_let_chain! {
[
@ -84,7 +84,7 @@ impl ReturnPass {
}
}
fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) {
fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) {
if in_external_macro(cx, note_span) {return;}
span_lint(cx, LET_AND_RETURN, lint_span,
"returning the result of a let binding. \
@ -100,8 +100,10 @@ impl LintPass for ReturnPass {
fn get_lints(&self) -> LintArray {
lint_array!(NEEDLESS_RETURN, LET_AND_RETURN)
}
}
fn check_fn(&mut self, cx: &Context, _: FnKind, _: &FnDecl,
impl LateLintPass for ReturnPass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl,
block: &Block, _: Span, _: NodeId) {
self.check_block_return(cx, block);
self.check_let_return(cx, block);

View File

@ -4,7 +4,7 @@ use reexport::*;
use syntax::codemap::Span;
use rustc_front::visit::FnKind;
use rustc::lint::{Context, Level, Lint, LintArray, LintPass};
use rustc::lint::*;
use rustc::middle::def::Def::{DefVariant, DefStruct};
use utils::{in_external_macro, snippet, span_lint, span_note_and_lint};
@ -25,14 +25,17 @@ impl LintPass for ShadowPass {
lint_array!(SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED)
}
fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl,
}
impl LateLintPass for ShadowPass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl,
block: &Block, _: Span, _: NodeId) {
if in_external_macro(cx, block.span) { return; }
check_fn(cx, decl, block);
}
}
fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) {
fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) {
let mut bindings = Vec::new();
for arg in &decl.inputs {
if let PatIdent(_, ident, _) = arg.pat.node {
@ -42,7 +45,7 @@ fn check_fn(cx: &Context, decl: &FnDecl, block: &Block) {
check_block(cx, block, &mut bindings);
}
fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<(Name, Span)>) {
fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) {
let len = bindings.len();
for stmt in &block.stmts {
match stmt.node {
@ -55,7 +58,7 @@ fn check_block(cx: &Context, block: &Block, bindings: &mut Vec<(Name, Span)>) {
bindings.truncate(len);
}
fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
if in_external_macro(cx, decl.span) { return; }
if let DeclLocal(ref local) = decl.node {
let Local{ ref pat, ref ty, ref init, id: _, span } = **local;
@ -69,14 +72,14 @@ fn check_decl(cx: &Context, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
}
}
fn is_binding(cx: &Context, pat: &Pat) -> bool {
fn is_binding(cx: &LateContext, pat: &Pat) -> bool {
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(DefVariant(..)) | Some(DefStruct(..)) => false,
_ => true
}
}
fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span,
fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span,
bindings: &mut Vec<(Name, Span)>) {
//TODO: match more stuff / destructuring
match pat.node {
@ -153,9 +156,9 @@ fn check_pat(cx: &Context, pat: &Pat, init: &Option<&Expr>, span: Span,
}
}
fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init:
fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, lspan: Span, init:
&Option<T>, prev_span: Span) where T: Deref<Target=Expr> {
fn note_orig(cx: &Context, lint: &'static Lint, span: Span) {
fn note_orig(cx: &LateContext, lint: &'static Lint, span: Span) {
if cx.current_level(lint) != Level::Allow {
cx.sess().span_note(span, "previous binding is here");
}
@ -191,10 +194,10 @@ fn lint_shadow<T>(cx: &Context, name: Name, span: Span, lspan: Span, init:
}
}
fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
if in_external_macro(cx, expr.span) { return; }
match expr.node {
ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
ExprUnary(_, ref e) | ExprField(ref e, _) |
ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(None, ref e)
=> { check_expr(cx, e, bindings) },
ExprBox(Some(ref place), ref e) => {
@ -233,7 +236,7 @@ fn check_expr(cx: &Context, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
}
}
fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
match ty.node {
TyParen(ref sty) | TyObjectSum(ref sty, _) |
TyVec(ref sty) => check_ty(cx, sty, bindings),
@ -252,7 +255,6 @@ fn check_ty(cx: &Context, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
fn is_self_shadow(name: Name, expr: &Expr) -> bool {
match expr.node {
ExprBox(_, ref inner) |
ExprParen(ref inner) |
ExprAddrOf(_, ref inner) => is_self_shadow(name, inner),
ExprBlock(ref block) => block.stmts.is_empty() && block.expr.as_ref().
map_or(false, |ref e| is_self_shadow(name, e)),
@ -275,7 +277,7 @@ fn contains_self(name: Name, expr: &Expr) -> bool {
// no subexprs
ExprLit(_) => false,
// one subexpr
ExprUnary(_, ref e) | ExprParen(ref e) | ExprField(ref e, _) |
ExprUnary(_, ref e) | ExprField(ref e, _) |
ExprTupField(ref e, _) | ExprAddrOf(_, ref e) | ExprBox(_, ref e) |
ExprCast(ref e, _) =>
contains_self(name, e),

View File

@ -30,8 +30,10 @@ impl LintPass for StringAdd {
fn get_lints(&self) -> LintArray {
lint_array!(STRING_ADD, STRING_ADD_ASSIGN)
}
}
fn check_expr(&mut self, cx: &Context, e: &Expr) {
impl LateLintPass for StringAdd {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let &ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) = &e.node {
if is_string(cx, left) {
if let Allow = cx.current_level(STRING_ADD_ASSIGN) {
@ -59,18 +61,17 @@ impl LintPass for StringAdd {
}
}
fn is_string(cx: &Context, e: &Expr) -> bool {
fn is_string(cx: &LateContext, e: &Expr) -> bool {
match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &STRING_PATH)
}
fn is_add(cx: &Context, src: &Expr, target: &Expr) -> bool {
fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool {
match src.node {
ExprBinary(Spanned{ node: BiAdd, .. }, ref left, _) =>
is_exp_equal(cx, target, left),
ExprBlock(ref block) => block.stmts.is_empty() &&
block.expr.as_ref().map_or(false,
|expr| is_add(cx, expr, target)),
ExprParen(ref expr) => is_add(cx, expr, target),
_ => false
}
}

View File

@ -26,8 +26,10 @@ impl LintPass for TypePass {
fn get_lints(&self) -> LintArray {
lint_array!(BOX_VEC, LINKEDLIST)
}
}
fn check_ty(&mut self, cx: &Context, ast_ty: &Ty) {
impl LateLintPass for TypePass {
fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) {
if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
if let ty::TyBox(ref inner) = ty.sty {
if match_type(cx, inner, &VEC_PATH) {
@ -53,7 +55,7 @@ pub struct LetPass;
declare_lint!(pub LET_UNIT_VALUE, Warn,
"creating a let binding to a value of unit type, which usually can't be used afterwards");
fn check_let_unit(cx: &Context, decl: &Decl) {
fn check_let_unit(cx: &LateContext, decl: &Decl) {
if let DeclLocal(ref local) = decl.node {
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
if *bindtype == ty::TyTuple(vec![]) {
@ -70,8 +72,10 @@ impl LintPass for LetPass {
fn get_lints(&self) -> LintArray {
lint_array!(LET_UNIT_VALUE)
}
}
fn check_decl(&mut self, cx: &Context, decl: &Decl) {
impl LateLintPass for LetPass {
fn check_decl(&mut self, cx: &LateContext, decl: &Decl) {
check_let_unit(cx, decl)
}
}
@ -86,8 +90,10 @@ impl LintPass for UnitCmp {
fn get_lints(&self) -> LintArray {
lint_array!(UNIT_CMP)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for UnitCmp {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if in_macro(cx, expr.span) { return; }
if let ExprBinary(ref cmp, ref left, _) = expr.node {
let op = cmp.node;
@ -135,7 +141,7 @@ fn is_isize_or_usize(typ: &ty::TyS) -> bool {
}
}
fn span_precision_loss_lint(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) {
fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) {
let mantissa_nbits = if cast_to_f64 {52} else {23};
let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
let arch_dependent_str = "on targets with 64-bit wide pointers ";
@ -154,7 +160,7 @@ enum ArchSuffix {
_32, _64, None
}
fn check_truncation_and_wrapping(cx: &Context, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) {
fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) {
let arch_64_suffix = " on targets with 64-bit wide pointers";
let arch_32_suffix = " on targets with 32-bit wide pointers";
let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
@ -207,8 +213,10 @@ impl LintPass for CastPass {
CAST_POSSIBLE_TRUNCATION,
CAST_POSSIBLE_WRAP)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for CastPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCast(ref ex, _) = expr.node {
let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr));
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
@ -262,16 +270,18 @@ impl LintPass for TypeComplexityPass {
fn get_lints(&self) -> LintArray {
lint_array!(TYPE_COMPLEXITY)
}
}
fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
impl LateLintPass for TypeComplexityPass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
check_fndecl(cx, decl);
}
fn check_struct_field(&mut self, cx: &Context, field: &StructField) {
fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) {
check_type(cx, &field.node.ty);
}
fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) {
fn check_variant(&mut self, cx: &LateContext, var: &Variant, _: &Generics) {
// StructVariant is covered by check_struct_field
if let TupleVariantKind(ref args) = var.node.kind {
for arg in args {
@ -280,7 +290,7 @@ impl LintPass for TypeComplexityPass {
}
}
fn check_item(&mut self, cx: &Context, item: &Item) {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
match item.node {
ItemStatic(ref ty, _, _) |
ItemConst(ref ty, _) => check_type(cx, ty),
@ -289,7 +299,7 @@ impl LintPass for TypeComplexityPass {
}
}
fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
match item.node {
ConstTraitItem(ref ty, _) |
TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty),
@ -299,7 +309,7 @@ impl LintPass for TypeComplexityPass {
}
}
fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
match item.node {
ConstImplItem(ref ty, _) |
TypeImplItem(ref ty) => check_type(cx, ty),
@ -308,14 +318,14 @@ impl LintPass for TypeComplexityPass {
}
}
fn check_local(&mut self, cx: &Context, local: &Local) {
fn check_local(&mut self, cx: &LateContext, local: &Local) {
if let Some(ref ty) = local.ty {
check_type(cx, ty);
}
}
}
fn check_fndecl(cx: &Context, decl: &FnDecl) {
fn check_fndecl(cx: &LateContext, decl: &FnDecl) {
for arg in &decl.inputs {
check_type(cx, &arg.ty);
}
@ -324,7 +334,7 @@ fn check_fndecl(cx: &Context, decl: &FnDecl) {
}
}
fn check_type(cx: &Context, ty: &Ty) {
fn check_type(cx: &LateContext, ty: &Ty) {
if in_macro(cx, ty.span) { return; }
let score = {
let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };

View File

@ -25,8 +25,10 @@ impl LintPass for Unicode {
fn get_lints(&self) -> LintArray {
lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC)
}
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
impl LateLintPass for Unicode {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprLit(ref lit) = expr.node {
if let LitStr(_, _) = lit.node {
check_str(cx, lit.span)
@ -47,7 +49,7 @@ fn escape<T: Iterator<Item=char>>(s: T) -> String {
result
}
fn check_str(cx: &Context, span: Span) {
fn check_str(cx: &LateContext, span: Span) {
let string = snippet(cx, span, "");
if string.contains('\u{200B}') {
span_help_and_lint(cx, ZERO_WIDTH_SPACE, span,

View File

@ -16,7 +16,7 @@ pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
/// returns true this expn_info was expanded by any macro
pub fn in_macro(cx: &Context, span: Span) -> bool {
pub fn in_macro(cx: &LateContext, span: Span) -> bool {
cx.sess().codemap().with_expn_info(span.expn_id,
|info| info.map_or(false, |i| {
match i.callee.format {
@ -28,10 +28,10 @@ pub fn in_macro(cx: &Context, span: Span) -> bool {
/// returns true if the macro that expanded the crate was outside of
/// the current crate or was a compiler plugin
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool {
/// invokes in_macro with the expansion info of the given span
/// slightly heavy, try to use this after other checks have already happened
fn in_macro_ext(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool {
// no ExpnInfo = no macro
opt_info.map_or(false, |info| {
match info.callee.format {
@ -65,12 +65,12 @@ pub fn in_external_macro(cx: &Context, span: Span) -> bool {
/// check if a DefId's path matches the given absolute type path
/// usage e.g. with
/// `match_def_path(cx, id, &["core", "option", "Option"])`
pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool {
pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p))
}
/// check if type is struct or enum type with given def path
pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool {
match ty.sty {
ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => {
match_def_path(cx, adt.did, path)
@ -82,7 +82,7 @@ pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
}
/// check if method call given in "expr" belongs to given trait
pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool {
pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool {
let method_call = ty::MethodCall::expr(expr.id);
let trt_id = cx.tcx.tables
.borrow().method_map.get(&method_call)
@ -102,7 +102,7 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool {
}
/// get the name of the item the expression is in, if available
pub fn get_item_name(cx: &Context, expr: &Expr) -> Option<Name> {
pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> {
let parent_id = cx.tcx.map.get_parent(expr.id);
match cx.tcx.map.find(parent_id) {
Some(NodeItem(&Item{ ref ident, .. })) |
@ -116,7 +116,7 @@ pub fn get_item_name(cx: &Context, expr: &Expr) -> Option<Name> {
/// convert a span to a code snippet if available, otherwise use default, e.g.
/// `snippet(cx, expr.span, "..")`
pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default))
}
@ -124,13 +124,13 @@ pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
/// `snippet(cx, expr.span, "..")`
/// This trims the code of indentation, except for the first line
/// Use it for blocks or block-like things which need to be printed as such
pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
let snip = snippet(cx, span, default);
trim_multiline(snip, true)
}
/// Like snippet_block, but add braces if the expr is not an ExprBlock
pub fn expr_block<'a>(cx: &Context, expr: &Expr, default: &'a str) -> Cow<'a, str> {
pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, default: &'a str) -> Cow<'a, str> {
let code = snippet_block(cx, expr.span, default);
if let ExprBlock(_) = expr.node {
code
@ -169,7 +169,7 @@ fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> {
}
/// get a parent expr if any this is useful to constrain a lint
pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> {
pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> {
let map = &cx.tcx.map;
let node_id : NodeId = e.id;
let parent_id : NodeId = map.get_parent_node(node_id);
@ -179,7 +179,7 @@ pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> {
}
#[cfg(not(feature="structured_logging"))]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
cx.span_lint(lint, sp, msg);
if cx.current_level(lint) != Level::Allow {
cx.sess().fileline_help(sp, &format!("for further information visit \
@ -189,7 +189,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
}
#[cfg(feature="structured_logging")]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
// lint.name / lint.desc is can give details of the lint
// cx.sess().codemap() has all these nice functions for line/column/snippet details
// http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string
@ -201,7 +201,7 @@ pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
}
}
pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span,
pub fn span_help_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span,
msg: &str, help: &str) {
cx.span_lint(lint, span, msg);
if cx.current_level(lint) != Level::Allow {
@ -211,7 +211,7 @@ pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span,
}
}
pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span,
pub fn span_note_and_lint<T: LintContext>(cx: &T, lint: &'static Lint, span: Span,
msg: &str, note_span: Span, note: &str) {
cx.span_lint(lint, span, msg);
if cx.current_level(lint) != Level::Allow {

View File

@ -12,7 +12,7 @@ fn main() {
let mut x = 1;
let x = &mut x; //~ERROR: x is shadowed by itself in &mut x
let x = { x }; //~ERROR: x is shadowed by itself in { x }
let x = (&*x); //~ERROR: x is shadowed by itself in (&*x)
let x = (&*x); //~ERROR: x is shadowed by itself in &*x
let x = { *x + 1 }; //~ERROR: x is shadowed by { *x + 1 } which reuses
let x = id(x); //~ERROR: x is shadowed by id(x) which reuses
let x = (1, x); //~ERROR: x is shadowed by (1, x) which reuses