mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 17:53:56 +00:00
Merge branch 'pr-704'
Conflicts: src/len_zero.rs
This commit is contained in:
commit
f13b841282
@ -1,8 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use std::f64::consts as f64;
|
||||
use utils::span_lint;
|
||||
use syntax::ast::{Lit, LitKind, FloatTy};
|
||||
use utils::span_lint;
|
||||
|
||||
/// **What it does:** This lint checks for floating point literals that approximate constants which are defined in [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants) or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant.
|
||||
///
|
||||
|
@ -1,12 +1,12 @@
|
||||
//! checks for attributes
|
||||
|
||||
use reexport::*;
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use semver::Version;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::attr::*;
|
||||
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind};
|
||||
use syntax::attr::*;
|
||||
use syntax::codemap::Span;
|
||||
use utils::{in_macro, match_path, span_lint, BEGIN_UNWIND};
|
||||
|
||||
/// **What it does:** This lint checks for items annotated with `#[inline(always)]`, unless the annotated function is empty or simply panics.
|
||||
|
@ -3,8 +3,8 @@ use rustc::middle::const_eval::lookup_const_by_id;
|
||||
use rustc::middle::def::{Def, PathResolution};
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::util::is_comparison_binop;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::span_lint;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_front::hir::*;
|
||||
use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass};
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::{Visitor, walk_expr};
|
||||
use utils::*;
|
||||
|
||||
|
@ -95,9 +95,7 @@ impl PartialEq for Constant {
|
||||
(&Constant::Byte(l), &Constant::Byte(r)) => l == r,
|
||||
(&Constant::Char(l), &Constant::Char(r)) => l == r,
|
||||
(&Constant::Int(0, _, _), &Constant::Int(0, _, _)) => true,
|
||||
(&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => {
|
||||
lv == rv && lneg == rneg
|
||||
}
|
||||
(&Constant::Int(lv, _, lneg), &Constant::Int(rv, _, rneg)) => lv == rv && lneg == rneg,
|
||||
(&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => {
|
||||
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have
|
||||
// `Fw32 == Fw64` so don’t compare them
|
||||
@ -116,7 +114,9 @@ impl PartialEq for Constant {
|
||||
}
|
||||
|
||||
impl Hash for Constant {
|
||||
fn hash<H>(&self, state: &mut H) where H: Hasher {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where H: Hasher
|
||||
{
|
||||
match *self {
|
||||
Constant::Str(ref s, ref k) => {
|
||||
s.hash(state);
|
||||
@ -144,7 +144,7 @@ impl Hash for Constant {
|
||||
Constant::Bool(b) => {
|
||||
b.hash(state);
|
||||
}
|
||||
Constant::Vec(ref v) | Constant::Tuple(ref v)=> {
|
||||
Constant::Vec(ref v) | Constant::Tuple(ref v) => {
|
||||
v.hash(state);
|
||||
}
|
||||
Constant::Repeat(ref c, l) => {
|
||||
@ -210,7 +210,9 @@ fn constant_not(o: Constant) -> Option<Constant> {
|
||||
use self::Constant::*;
|
||||
match o {
|
||||
Bool(b) => Some(Bool(!b)),
|
||||
Int(value, LitIntType::Signed(ity), Sign::Plus) if value != ::std::u64::MAX => Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus)),
|
||||
Int(value, LitIntType::Signed(ity), Sign::Plus) if value != ::std::u64::MAX => {
|
||||
Some(Int(value + 1, LitIntType::Signed(ity), Sign::Minus))
|
||||
}
|
||||
Int(0, LitIntType::Signed(ity), Sign::Minus) => Some(Int(1, LitIntType::Signed(ity), Sign::Minus)),
|
||||
Int(value, LitIntType::Signed(ity), Sign::Minus) => Some(Int(value - 1, LitIntType::Signed(ity), Sign::Plus)),
|
||||
Int(value, LitIntType::Unsigned(ity), Sign::Plus) => {
|
||||
@ -224,7 +226,7 @@ fn constant_not(o: Constant) -> Option<Constant> {
|
||||
} // refuse to guess
|
||||
};
|
||||
Some(Int(!value & mask, LitIntType::Unsigned(ity), Sign::Plus))
|
||||
},
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -388,7 +390,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||
(Constant::Byte(l8), Constant::Byte(r8)) => l8.checked_add(r8).map(Constant::Byte),
|
||||
(Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => {
|
||||
add_ints(l64, r64, lty, rty, lsign, rsign)
|
||||
},
|
||||
}
|
||||
// TODO: float (would need bignum library?)
|
||||
_ => None,
|
||||
}
|
||||
@ -406,7 +408,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||
}
|
||||
(Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => {
|
||||
add_ints(l64, r64, lty, rty, lsign, neg_sign(rsign))
|
||||
},
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
@ -438,7 +440,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||
match (l, r) {
|
||||
(Constant::Int(l64, lty, lsign), Constant::Int(r64, rty, rsign)) => {
|
||||
f(l64, r64).and_then(|value| {
|
||||
let sign = if lsign == rsign { Sign::Plus } else { Sign::Minus };
|
||||
let sign = if lsign == rsign {
|
||||
Sign::Plus
|
||||
} else {
|
||||
Sign::Minus
|
||||
};
|
||||
unify_int_type(lty, rty).map(|ty| Constant::Int(value, ty, sign))
|
||||
})
|
||||
}
|
||||
@ -504,19 +510,28 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||
}
|
||||
|
||||
fn add_ints(l64: u64, r64: u64, lty: LitIntType, rty: LitIntType, lsign: Sign, rsign: Sign) -> Option<Constant> {
|
||||
let ty = if let Some(ty) = unify_int_type(lty, rty) { ty } else { return None; };
|
||||
let ty = if let Some(ty) = unify_int_type(lty, rty) {
|
||||
ty
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
match (lsign, rsign) {
|
||||
(Sign::Plus, Sign::Plus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Plus)),
|
||||
(Sign::Plus, Sign::Minus) => if r64 > l64 {
|
||||
Some(Constant::Int(r64 - l64, ty, Sign::Minus))
|
||||
} else {
|
||||
Some(Constant::Int(l64 - r64, ty, Sign::Plus))
|
||||
},
|
||||
(Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)),
|
||||
(Sign::Minus, Sign::Plus) => if l64 > r64 {
|
||||
Some(Constant::Int(l64 - r64, ty, Sign::Minus))
|
||||
} else {
|
||||
Some(Constant::Int(r64 - l64, ty, Sign::Plus))
|
||||
},
|
||||
(Sign::Plus, Sign::Minus) => {
|
||||
if r64 > l64 {
|
||||
Some(Constant::Int(r64 - l64, ty, Sign::Minus))
|
||||
} else {
|
||||
Some(Constant::Int(l64 - r64, ty, Sign::Plus))
|
||||
}
|
||||
}
|
||||
(Sign::Minus, Sign::Minus) => l64.checked_add(r64).map(|v| Constant::Int(v, ty, Sign::Minus)),
|
||||
(Sign::Minus, Sign::Plus) => {
|
||||
if l64 > r64 {
|
||||
Some(Constant::Int(l64 - r64, ty, Sign::Minus))
|
||||
} else {
|
||||
Some(Constant::Int(r64 - l64, ty, Sign::Plus))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,11 +61,7 @@ pub struct CopyAndPaste;
|
||||
|
||||
impl LintPass for CopyAndPaste {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array![
|
||||
IFS_SAME_COND,
|
||||
IF_SAME_THEN_ELSE,
|
||||
MATCH_SAME_ARMS
|
||||
]
|
||||
lint_array![IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,35 +85,43 @@ impl LateLintPass for CopyAndPaste {
|
||||
|
||||
/// Implementation of `IF_SAME_THEN_ELSE`.
|
||||
fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
|
||||
let hash : &Fn(&&Block) -> u64 = &|block| -> u64 {
|
||||
let hash: &Fn(&&Block) -> u64 = &|block| -> u64 {
|
||||
let mut h = SpanlessHash::new(cx);
|
||||
h.hash_block(block);
|
||||
h.finish()
|
||||
};
|
||||
|
||||
let eq : &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool {
|
||||
let eq: &Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool {
|
||||
SpanlessEq::new(cx).eq_block(lhs, rhs)
|
||||
};
|
||||
|
||||
if let Some((i, j)) = search_same(blocks, hash, eq) {
|
||||
span_note_and_lint(cx, IF_SAME_THEN_ELSE, j.span, "this `if` has identical blocks", i.span, "same as this");
|
||||
span_note_and_lint(cx,
|
||||
IF_SAME_THEN_ELSE,
|
||||
j.span,
|
||||
"this `if` has identical blocks",
|
||||
i.span,
|
||||
"same as this");
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `IFS_SAME_COND`.
|
||||
fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) {
|
||||
let hash : &Fn(&&Expr) -> u64 = &|expr| -> u64 {
|
||||
let hash: &Fn(&&Expr) -> u64 = &|expr| -> u64 {
|
||||
let mut h = SpanlessHash::new(cx);
|
||||
h.hash_expr(expr);
|
||||
h.finish()
|
||||
};
|
||||
|
||||
let eq : &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool {
|
||||
SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs)
|
||||
};
|
||||
let eq: &Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };
|
||||
|
||||
if let Some((i, j)) = search_same(conds, hash, eq) {
|
||||
span_note_and_lint(cx, IFS_SAME_COND, j.span, "this `if` has the same condition as a previous if", i.span, "same as this");
|
||||
span_note_and_lint(cx,
|
||||
IFS_SAME_COND,
|
||||
j.span,
|
||||
"this `if` has the same condition as a previous if",
|
||||
i.span,
|
||||
"same as this");
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +141,12 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) {
|
||||
|
||||
if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node {
|
||||
if let Some((i, j)) = search_same(&**arms, hash, eq) {
|
||||
span_note_and_lint(cx, MATCH_SAME_ARMS, j.body.span, "this `match` has identical arm bodies", i.body.span, "same as this");
|
||||
span_note_and_lint(cx,
|
||||
MATCH_SAME_ARMS,
|
||||
j.body.span,
|
||||
"this `match` has identical arm bodies",
|
||||
i.body.span,
|
||||
"same as this");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,8 +164,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
|
||||
|
||||
if let Some(ref else_expr) = *else_expr {
|
||||
expr = else_expr;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -188,7 +196,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
|
||||
if let Some(ref as_pat) = *as_pat {
|
||||
bindings_impl(cx, as_pat, map);
|
||||
}
|
||||
},
|
||||
}
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
for pat in fields {
|
||||
bindings_impl(cx, &pat.node.pat, map);
|
||||
@ -210,7 +218,12 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
|
||||
bindings_impl(cx, pat, map);
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(..) | PatKind::Lit(..) | PatKind::QPath(..) | PatKind::Range(..) | PatKind::Wild | PatKind::Path(..) => (),
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Lit(..) |
|
||||
PatKind::QPath(..) |
|
||||
PatKind::Range(..) |
|
||||
PatKind::Wild |
|
||||
PatKind::Path(..) => (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,36 +232,35 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
|
||||
result
|
||||
}
|
||||
|
||||
fn search_same<T, Hash, Eq>(exprs: &[T],
|
||||
hash: Hash,
|
||||
eq: Eq) -> Option<(&T, &T)>
|
||||
where Hash: Fn(&T) -> u64,
|
||||
Eq: Fn(&T, &T) -> bool {
|
||||
fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
|
||||
where Hash: Fn(&T) -> u64,
|
||||
Eq: Fn(&T, &T) -> bool
|
||||
{
|
||||
// common cases
|
||||
if exprs.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
else if exprs.len() == 2 {
|
||||
} else if exprs.len() == 2 {
|
||||
return if eq(&exprs[0], &exprs[1]) {
|
||||
Some((&exprs[0], &exprs[1]))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let mut map : HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len());
|
||||
let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len());
|
||||
|
||||
for expr in exprs {
|
||||
match map.entry(hash(expr)) {
|
||||
Entry::Occupied(o) => {
|
||||
for o in o.get() {
|
||||
if eq(&o, expr) {
|
||||
return Some((&o, expr))
|
||||
return Some((&o, expr));
|
||||
}
|
||||
}
|
||||
}
|
||||
Entry::Vacant(v) => { v.insert(vec![expr]); }
|
||||
Entry::Vacant(v) => {
|
||||
v.insert(vec![expr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
//! calculate cyclomatic complexity and warn about overly complex functions
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::middle::cfg::CFG;
|
||||
use rustc::middle::ty;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::attr::*;
|
||||
use syntax::ast::Attribute;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::{Visitor, walk_expr};
|
||||
use syntax::ast::Attribute;
|
||||
use syntax::attr::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::{in_macro, LimitStack, span_help_and_lint};
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::middle::ty;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::DROP_PATH;
|
||||
use utils::{match_def_path, span_note_and_lint};
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
//! lint on `use`ing all variants of an enum
|
||||
|
||||
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext};
|
||||
use rustc_front::hir::*;
|
||||
use rustc::front::map::Node::NodeItem;
|
||||
use rustc::front::map::definitions::DefPathData;
|
||||
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext};
|
||||
use rustc::middle::ty::TyEnum;
|
||||
use utils::span_lint;
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::codemap::Span;
|
||||
use utils::span_lint;
|
||||
|
||||
/// **What it does:** Warns when `use`ing all variants of an enum
|
||||
///
|
||||
|
@ -1,10 +1,9 @@
|
||||
//! lint on enum variants that are prefixed or suffixed by the same characters
|
||||
|
||||
use rustc::lint::*;
|
||||
use syntax::attr::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::attr::*;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
use utils::span_help_and_lint;
|
||||
use utils::{camel_case_from, camel_case_until};
|
||||
|
||||
@ -95,7 +94,7 @@ impl EarlyLintPass for EnumVariantNames {
|
||||
} else if !post.is_empty() {
|
||||
("post", post)
|
||||
} else {
|
||||
return
|
||||
return;
|
||||
};
|
||||
span_help_and_lint(cx,
|
||||
ENUM_VARIANT_NAMES,
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::util as ast_util;
|
||||
|
||||
use utils::{SpanlessEq, span_lint};
|
||||
|
||||
/// **What it does:** This lint checks for equal operands to comparison, logical and bitwise,
|
||||
|
@ -1,13 +1,13 @@
|
||||
use rustc::lint::*;
|
||||
use rustc::front::map::Node::{NodeExpr, NodeStmt};
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit as visit;
|
||||
use rustc::middle::ty;
|
||||
use rustc::middle::ty::adjustment::AutoAdjustment;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::expr_use_visitor::*;
|
||||
use rustc::middle::infer;
|
||||
use rustc::middle::mem_categorization::{cmt, Categorization};
|
||||
use rustc::middle::ty::adjustment::AutoAdjustment;
|
||||
use rustc::middle::ty;
|
||||
use rustc::util::nodemap::NodeSet;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit as visit;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::codemap::Span;
|
||||
use utils::span_lint;
|
||||
|
@ -1,10 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::middle::ty;
|
||||
|
||||
use rustc_front::hir::*;
|
||||
use utils::{snippet_opt, span_lint_and_then, is_adjusted};
|
||||
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub struct EtaPass;
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use consts::{constant_simple, Constant, Sign};
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use consts::{constant_simple, Constant, Sign};
|
||||
use utils::{span_lint, snippet, in_macro};
|
||||
|
||||
/// **What it does:** This lint checks for identity operations, e.g. `x + 0`.
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! lint when items are used after statements
|
||||
|
||||
use rustc::lint::*;
|
||||
use syntax::attr::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::attr::*;
|
||||
use utils::in_macro;
|
||||
|
||||
/// **What it does:** This lints checks for items declared after some statement in a block
|
||||
|
@ -1,13 +1,10 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ast::Name;
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::ty::{self, MethodTraitItemId, ImplOrTraitItemId};
|
||||
|
||||
use syntax::ast::{Lit, LitKind};
|
||||
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ast::{Lit, LitKind, Name};
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use syntax::ptr::P;
|
||||
use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty};
|
||||
|
||||
/// **What it does:** This lint checks for getting the length of something via `.len()` just to compare to zero, and suggests using `.is_empty()` where applicable.
|
||||
|
@ -1,11 +1,10 @@
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
|
||||
use rustc::middle::def::Def;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
|
||||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
use syntax::codemap::Span;
|
||||
use utils::{in_external_macro, span_lint};
|
||||
|
||||
/// **What it does:** This lint checks for lifetime annotations which can be removed by relying on lifetime elision.
|
||||
|
87
src/loops.rs
87
src/loops.rs
@ -354,9 +354,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
|
||||
// linting condition: we only indexed one variable
|
||||
if visitor.indexed.len() == 1 {
|
||||
let (indexed, indexed_extent) = visitor.indexed
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or_else(|| unreachable!() /* len == 1 */);
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or_else(|| unreachable!() /* len == 1 */);
|
||||
|
||||
// ensure that the indexed variable was declared before the loop, see #601
|
||||
let pat_extent = cx.tcx.region_maps.var_scope(pat.id);
|
||||
@ -441,8 +441,12 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
|
||||
// who think that this will iterate from the larger value to the
|
||||
// smaller value.
|
||||
let (sup, eq) = match (start_idx, stop_idx) {
|
||||
(ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx),
|
||||
(ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => (start_idx > stop_idx, start_idx == stop_idx),
|
||||
(ConstVal::Int(start_idx), ConstVal::Int(stop_idx)) => {
|
||||
(start_idx > stop_idx, start_idx == stop_idx)
|
||||
}
|
||||
(ConstVal::Uint(start_idx), ConstVal::Uint(stop_idx)) => {
|
||||
(start_idx > stop_idx, start_idx == stop_idx)
|
||||
}
|
||||
_ => (false, false),
|
||||
};
|
||||
|
||||
@ -518,26 +522,25 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
|
||||
fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) {
|
||||
let ty = cx.tcx.expr_ty(arg);
|
||||
if match_type(cx, ty, &OPTION_PATH) {
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
FOR_LOOP_OVER_OPTION,
|
||||
arg.span,
|
||||
&format!("for loop over `{0}`, which is an `Option`. This is more readably written as \
|
||||
an `if let` statement.", snippet(cx, arg.span, "_")),
|
||||
&format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`",
|
||||
snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_"))
|
||||
);
|
||||
}
|
||||
else if match_type(cx, ty, &RESULT_PATH) {
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
FOR_LOOP_OVER_RESULT,
|
||||
arg.span,
|
||||
&format!("for loop over `{0}`, which is a `Result`. This is more readably written as \
|
||||
an `if let` statement.", snippet(cx, arg.span, "_")),
|
||||
&format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`",
|
||||
snippet(cx, pat.span, "_"), snippet(cx, arg.span, "_"))
|
||||
);
|
||||
span_help_and_lint(cx,
|
||||
FOR_LOOP_OVER_OPTION,
|
||||
arg.span,
|
||||
&format!("for loop over `{0}`, which is an `Option`. This is more readably written as an \
|
||||
`if let` statement.",
|
||||
snippet(cx, arg.span, "_")),
|
||||
&format!("consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`",
|
||||
snippet(cx, pat.span, "_"),
|
||||
snippet(cx, arg.span, "_")));
|
||||
} else if match_type(cx, ty, &RESULT_PATH) {
|
||||
span_help_and_lint(cx,
|
||||
FOR_LOOP_OVER_RESULT,
|
||||
arg.span,
|
||||
&format!("for loop over `{0}`, which is a `Result`. This is more readably written as an \
|
||||
`if let` statement.",
|
||||
snippet(cx, arg.span, "_")),
|
||||
&format!("consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`",
|
||||
snippet(cx, pat.span, "_"),
|
||||
snippet(cx, arg.span, "_")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,31 +596,29 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
|
||||
let (pat_span, kind) = match (&pat[0].node, &pat[1].node) {
|
||||
(key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"),
|
||||
(_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"),
|
||||
_ => return
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
|
||||
let arg_span = if let ExprAddrOf(_, ref expr) = arg.node {
|
||||
expr.span
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
arg.span
|
||||
};
|
||||
|
||||
if match_type(cx, ty, &HASHMAP_PATH) ||
|
||||
match_type(cx, ty, &BTREEMAP_PATH) {
|
||||
if match_type(cx, ty, &HASHMAP_PATH) || match_type(cx, ty, &BTREEMAP_PATH) {
|
||||
span_lint_and_then(cx,
|
||||
FOR_KV_MAP,
|
||||
expr.span,
|
||||
&format!("you seem to want to iterate on a map's {}", kind),
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"use the corresponding method",
|
||||
format!("for {} in {}.{}() {{...}}",
|
||||
snippet(cx, *pat_span, ".."),
|
||||
snippet(cx, arg_span, ".."),
|
||||
kind));
|
||||
});
|
||||
FOR_KV_MAP,
|
||||
expr.span,
|
||||
&format!("you seem to want to iterate on a map's {}", kind),
|
||||
|db| {
|
||||
db.span_suggestion(expr.span,
|
||||
"use the corresponding method",
|
||||
format!("for {} in {}.{}() {{...}}",
|
||||
snippet(cx, *pat_span, ".."),
|
||||
snippet(cx, arg_span, ".."),
|
||||
kind));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -635,7 +636,7 @@ fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
|
||||
};
|
||||
walk_expr(&mut visitor, body);
|
||||
!visitor.used
|
||||
},
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -650,7 +651,7 @@ impl<'a> Visitor<'a> for UsedVisitor {
|
||||
if let ExprPath(None, ref path) = expr.node {
|
||||
if path.segments.len() == 1 && path.segments[0].identifier == self.var {
|
||||
self.used = true;
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use utils::{CLONE_PATH, OPTION_PATH};
|
||||
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
|
||||
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
|
||||
use utils::{
|
||||
is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint,
|
||||
walk_ptrs_ty, walk_ptrs_ty_depth
|
||||
};
|
||||
|
||||
/// **What it does:** This lint checks for mapping clone() over an iterator.
|
||||
///
|
||||
|
@ -7,7 +7,6 @@ use rustc_front::hir::*;
|
||||
use std::cmp::Ordering;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use utils::{COW_PATH, OPTION_PATH, RESULT_PATH};
|
||||
use utils::{match_type, snippet, span_lint, span_note_and_lint, span_lint_and_then, in_external_macro, expr_block};
|
||||
|
||||
@ -139,20 +138,20 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
||||
if arms.len() == 2 &&
|
||||
arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
|
||||
arms[1].pats.len() == 1 && arms[1].guard.is_none() {
|
||||
let els = if is_unit_expr(&arms[1].body) {
|
||||
None
|
||||
} else if let ExprBlock(_) = arms[1].body.node {
|
||||
// matches with blocks that contain statements are prettier as `if let + else`
|
||||
Some(&*arms[1].body)
|
||||
} else {
|
||||
// allow match arms with just expressions
|
||||
return;
|
||||
};
|
||||
let ty = cx.tcx.expr_ty(ex);
|
||||
if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow {
|
||||
check_single_match_single_pattern(cx, ex, arms, expr, els);
|
||||
check_single_match_opt_like(cx, ex, arms, expr, ty, els);
|
||||
}
|
||||
let els = if is_unit_expr(&arms[1].body) {
|
||||
None
|
||||
} else if let ExprBlock(_) = arms[1].body.node {
|
||||
// matches with blocks that contain statements are prettier as `if let + else`
|
||||
Some(&*arms[1].body)
|
||||
} else {
|
||||
// allow match arms with just expressions
|
||||
return;
|
||||
};
|
||||
let ty = cx.tcx.expr_ty(ex);
|
||||
if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow {
|
||||
check_single_match_single_pattern(cx, ex, arms, expr, els);
|
||||
check_single_match_opt_like(cx, ex, arms, expr, ty, els);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,11 +193,11 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
|
||||
let path = match arms[1].pats[0].node {
|
||||
PatKind::TupleStruct(ref path, Some(ref inner)) => {
|
||||
// contains any non wildcard patterns? e.g. Err(err)
|
||||
if inner.iter().any(|pat| if let PatKind::Wild = pat.node { false } else { true }) {
|
||||
if inner.iter().any(|pat| pat.node != PatKind::Wild) {
|
||||
return;
|
||||
}
|
||||
path.to_string()
|
||||
},
|
||||
}
|
||||
PatKind::TupleStruct(ref path, None) => path.to_string(),
|
||||
PatKind::Ident(BindByValue(MutImmutable), ident, None) => ident.node.to_string(),
|
||||
_ => return,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial};
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc::middle::const_eval::{ConstVal, eval_const_expr_partial};
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc::middle::subst::{Subst, TypeSpace};
|
||||
use rustc::middle::ty;
|
||||
use rustc_front::hir::*;
|
||||
@ -8,14 +9,12 @@ use std::borrow::Cow;
|
||||
use std::{fmt, iter};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ptr::P;
|
||||
|
||||
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, match_path, match_trait_method,
|
||||
match_type, method_chain_args, snippet, snippet_opt, span_lint, span_lint_and_then, span_note_and_lint,
|
||||
walk_ptrs_ty, walk_ptrs_ty_depth};
|
||||
use utils::{BTREEMAP_ENTRY_PATH, DEFAULT_TRAIT_PATH, HASHMAP_ENTRY_PATH, OPTION_PATH, RESULT_PATH, STRING_PATH,
|
||||
VEC_PATH,};
|
||||
VEC_PATH};
|
||||
use utils::MethodArgs;
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MethodsPass;
|
||||
@ -439,12 +438,10 @@ impl LateLintPass for MethodsPass {
|
||||
|
||||
if let Some(&ret_ty) = ret_ty {
|
||||
ret_ty.walk().any(|t| t == ty)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
@ -961,9 +958,9 @@ impl SelfKind {
|
||||
fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool {
|
||||
match (self, slf) {
|
||||
(&SelfKind::Value, &SelfValue(_)) |
|
||||
(&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) |
|
||||
(&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) |
|
||||
(&SelfKind::No, &SelfStatic) => true,
|
||||
(&SelfKind::Ref, &SelfRegion(_, Mutability::MutImmutable, _)) |
|
||||
(&SelfKind::RefMut, &SelfRegion(_, Mutability::MutMutable, _)) |
|
||||
(&SelfKind::No, &SelfStatic) => true,
|
||||
(&SelfKind::Ref, &SelfValue(_)) | (&SelfKind::RefMut, &SelfValue(_)) => allow_value_for_ref,
|
||||
(_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref),
|
||||
_ => false,
|
||||
@ -973,10 +970,10 @@ impl SelfKind {
|
||||
fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool {
|
||||
match (self, &ty.node) {
|
||||
(&SelfKind::Value, &TyPath(..)) |
|
||||
(&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) |
|
||||
(&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true,
|
||||
(&SelfKind::Ref, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) |
|
||||
(&SelfKind::RefMut, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true,
|
||||
(&SelfKind::Ref, &TyPath(..)) |
|
||||
(&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref,
|
||||
(&SelfKind::RefMut, &TyPath(..)) => allow_value_for_ref,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use consts::{Constant, constant_simple};
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ptr::P;
|
||||
use std::cmp::{PartialOrd, Ordering};
|
||||
|
||||
use consts::{Constant, constant_simple};
|
||||
use syntax::ptr::P;
|
||||
use utils::{match_def_path, span_lint};
|
||||
use self::MinMax::{Min, Max};
|
||||
|
||||
/// **What it does:** This lint checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant.
|
||||
///
|
||||
@ -36,7 +34,7 @@ impl LateLintPass for MinMaxPass {
|
||||
return;
|
||||
}
|
||||
match (outer_max, outer_c.partial_cmp(&inner_c)) {
|
||||
(_, None) | (Max, Some(Ordering::Less)) | (Min, Some(Ordering::Greater)) => (),
|
||||
(_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (),
|
||||
_ => {
|
||||
span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result");
|
||||
}
|
||||
@ -58,9 +56,9 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'
|
||||
let def_id = cx.tcx.def_map.borrow()[&path.id].def_id();
|
||||
|
||||
if match_def_path(cx, def_id, &["core", "cmp", "min"]) {
|
||||
fetch_const(args, Min)
|
||||
fetch_const(args, MinMax::Min)
|
||||
} else if match_def_path(cx, def_id, &["core", "cmp", "max"]) {
|
||||
fetch_const(args, Max)
|
||||
fetch_const(args, MinMax::Max)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
17
src/misc.rs
17
src/misc.rs
@ -1,15 +1,14 @@
|
||||
use rustc::lint::*;
|
||||
use syntax::ptr::P;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::const_eval::ConstVal::Float;
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc::middle::const_eval::eval_const_expr_partial;
|
||||
use rustc::middle::ty;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::FnKind;
|
||||
use rustc_front::util::{is_comparison_binop, binop_to_string};
|
||||
use syntax::codemap::{Span, Spanned, ExpnFormat};
|
||||
use rustc_front::intravisit::FnKind;
|
||||
use rustc::middle::ty;
|
||||
use rustc::middle::const_eval::ConstVal::Float;
|
||||
use rustc::middle::const_eval::eval_const_expr_partial;
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
|
||||
use syntax::ptr::P;
|
||||
use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint};
|
||||
use utils::{span_lint_and_then, walk_ptrs_ty, is_integer_literal, implements_trait};
|
||||
|
||||
|
@ -1,11 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::visit::FnKind;
|
||||
|
||||
use utils::{span_lint, span_help_and_lint};
|
||||
|
||||
/// **What it does:** This lint checks for structure field patterns bound to wildcards.
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::middle::ty::{TypeAndMut, TyRef};
|
||||
|
||||
use rustc_front::hir::*;
|
||||
use utils::{in_external_macro, span_lint};
|
||||
|
||||
/// **What it does:** This lint checks for instances of `mut mut` references.
|
||||
|
@ -1,8 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use utils::span_lint;
|
||||
use rustc::middle::ty::{TypeAndMut, TypeVariants, MethodCall, TyS};
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ptr::P;
|
||||
use utils::span_lint;
|
||||
|
||||
/// **What it does:** This lint detects giving a mutable reference to a function that only requires an immutable reference.
|
||||
///
|
||||
|
@ -3,12 +3,10 @@
|
||||
//! This lint is **warn** by default
|
||||
|
||||
use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext};
|
||||
use rustc_front::hir::Expr;
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::middle::ty;
|
||||
use rustc::middle::subst::ParamSpace;
|
||||
|
||||
use rustc::middle::ty;
|
||||
use rustc_front::hir::Expr;
|
||||
use syntax::ast;
|
||||
use utils::{span_lint, MUTEX_PATH, match_type};
|
||||
|
||||
/// **What it does:** This lint checks for usages of `Mutex<X>` where an atomic will do.
|
||||
|
@ -4,10 +4,8 @@
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::codemap::Spanned;
|
||||
|
||||
use utils::{span_lint, span_lint_and_then, snippet};
|
||||
|
||||
/// **What it does:** This lint checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggest using the condition directly.
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
|
||||
use utils::span_lint;
|
||||
use utils;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::middle::ty::TyStruct;
|
||||
use rustc_front::hir::{Expr, ExprStruct};
|
||||
|
||||
use utils::span_lint;
|
||||
|
||||
/// **What it does:** This lint warns on needlessly including a base struct on update when all fields are changed anyway.
|
||||
|
@ -1,10 +1,7 @@
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::middle::def::Def;
|
||||
use rustc_front::hir::{Expr, Expr_};
|
||||
use rustc_front::hir::{Stmt, StmtSemi};
|
||||
|
||||
use utils::in_macro;
|
||||
use utils::span_lint;
|
||||
use rustc_front::hir::{Expr, Expr_, Stmt, StmtSemi};
|
||||
use utils::{in_macro, span_lint};
|
||||
|
||||
/// **What it does:** This lint checks for statements which have no effect.
|
||||
///
|
||||
|
@ -1,8 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::{Expr, ExprMethodCall, ExprLit};
|
||||
use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH};
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use utils::{walk_ptrs_ty_depth, match_type, span_lint, OPEN_OPTIONS_PATH};
|
||||
|
||||
/// **What it does:** This lint checks for duplicate open options as well as combinations that make no sense.
|
||||
///
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::ast::LitKind;
|
||||
|
||||
use utils::{span_lint, in_external_macro, match_path, BEGIN_UNWIND};
|
||||
|
||||
/// **What it does:** This lint checks for missing parameters in `panic!`.
|
||||
|
@ -1,7 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::ast::*;
|
||||
|
||||
use syntax::codemap::Spanned;
|
||||
use utils::{span_lint, snippet};
|
||||
|
||||
/// **What it does:** This lint checks for operations where precedence may be unclear and suggests to add parentheses. Currently it catches the following:
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc::front::map::Node::{NodeItem, NodeImplItem};
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::front::map::Node::{NodeItem, NodeImplItem};
|
||||
use utils::{FMT_ARGUMENTV1_NEW_PATH, DEBUG_FMT_METHOD_PATH, IO_PRINT_PATH};
|
||||
use utils::{is_expn_of, match_path, span_lint};
|
||||
|
||||
|
@ -2,13 +2,12 @@
|
||||
//!
|
||||
//! This lint is **warn** by default
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::front::map::NodeItem;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::ty;
|
||||
|
||||
use utils::{span_lint, match_type};
|
||||
use rustc_front::hir::*;
|
||||
use utils::{STRING_PATH, VEC_PATH};
|
||||
use utils::{span_lint, match_type};
|
||||
|
||||
/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless the references are mutable.
|
||||
///
|
||||
|
39
src/regex.rs
39
src/regex.rs
@ -1,13 +1,13 @@
|
||||
use regex_syntax;
|
||||
use std::error::Error;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
||||
use rustc_front::hir::*;
|
||||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
use syntax::ast::{LitKind, NodeId};
|
||||
use syntax::codemap::{Span, BytePos};
|
||||
use syntax::parse::token::InternedString;
|
||||
use rustc_front::hir::*;
|
||||
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc::lint::*;
|
||||
|
||||
use utils::{is_expn_of, match_path, match_type, REGEX_NEW_PATH, span_lint, span_help_and_lint};
|
||||
|
||||
@ -54,7 +54,7 @@ declare_lint! {
|
||||
#[derive(Clone, Default)]
|
||||
pub struct RegexPass {
|
||||
spans: HashSet<Span>,
|
||||
last: Option<NodeId>
|
||||
last: Option<NodeId>,
|
||||
}
|
||||
|
||||
impl LintPass for RegexPass {
|
||||
@ -86,10 +86,10 @@ impl LateLintPass for RegexPass {
|
||||
self.last = Some(block.id);
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
fn check_block_post(&mut self, _: &LateContext, block: &Block) {
|
||||
if self.last.map_or(false, |id| block.id == id) {
|
||||
self.last = None;
|
||||
self.last = None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ impl LateLintPass for RegexPass {
|
||||
fn str_span(base: Span, s: &str, c: usize) -> Span {
|
||||
let lo = match s.char_indices().nth(c) {
|
||||
Some((b, _)) => base.lo + BytePos(b as u32),
|
||||
_ => base.hi
|
||||
_ => base.hi,
|
||||
};
|
||||
Span{ lo: lo, hi: lo, ..base }
|
||||
}
|
||||
@ -153,7 +153,7 @@ fn str_span(base: Span, s: &str, c: usize) -> Span {
|
||||
fn const_str(cx: &LateContext, e: &Expr) -> Option<InternedString> {
|
||||
match eval_const_expr_partial(cx.tcx, e, ExprTypeChecked, None) {
|
||||
Ok(ConstVal::Str(r)) => Some(r),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,20 +165,21 @@ fn is_trivial_regex(s: ®ex_syntax::Expr) -> Option<&'static str> {
|
||||
Expr::Literal {..} => Some("consider using `str::contains`"),
|
||||
Expr::Concat(ref exprs) => {
|
||||
match exprs.len() {
|
||||
2 => match (&exprs[0], &exprs[1]) {
|
||||
(&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"),
|
||||
(&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"),
|
||||
(&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"),
|
||||
_ => None,
|
||||
},
|
||||
2 => {
|
||||
match (&exprs[0], &exprs[1]) {
|
||||
(&Expr::StartText, &Expr::EndText) => Some("consider using `str::is_empty`"),
|
||||
(&Expr::StartText, &Expr::Literal {..}) => Some("consider using `str::starts_with`"),
|
||||
(&Expr::Literal {..}, &Expr::EndText) => Some("consider using `str::ends_with`"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
if let (&Expr::StartText, &Expr::Literal {..}, &Expr::EndText) = (&exprs[0], &exprs[1], &exprs[2]) {
|
||||
Some("consider using `==` on `str`s")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use rustc::lint::*;
|
||||
use syntax::ast::*;
|
||||
// use reexport::*;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use syntax::visit::FnKind;
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
use std::ops::Deref;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::intravisit::{Visitor, FnKind};
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::def::Def;
|
||||
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::{Visitor, FnKind};
|
||||
use std::ops::Deref;
|
||||
use syntax::codemap::Span;
|
||||
use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint, DiagnosticWrapper};
|
||||
|
||||
/// **What it does:** This lint checks for bindings that shadow other bindings already in scope, while just changing reference level or mutability.
|
||||
|
@ -6,10 +6,9 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Spanned;
|
||||
|
||||
use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr};
|
||||
use utils::SpanlessEq;
|
||||
use utils::STRING_PATH;
|
||||
use utils::SpanlessEq;
|
||||
use utils::{match_type, span_lint, walk_ptrs_ty, get_parent_expr};
|
||||
|
||||
/// **What it does:** This lint matches code of the form `x = x + y` (without `let`!).
|
||||
///
|
||||
|
@ -1,6 +1,5 @@
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc_front::hir::{Expr, ExprAssign, ExprField, ExprStruct, ExprTup, ExprTupField};
|
||||
|
||||
use utils::is_adjusted;
|
||||
use utils::span_lint;
|
||||
|
||||
|
34
src/types.rs
34
src/types.rs
@ -1,13 +1,12 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use rustc_front::util::{is_comparison_binop, binop_to_string};
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::intravisit::{FnKind, Visitor, walk_ty};
|
||||
use rustc::middle::ty;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::const_eval;
|
||||
use rustc::middle::ty;
|
||||
use rustc_front::hir::*;
|
||||
use rustc_front::intravisit::{FnKind, Visitor, walk_ty};
|
||||
use rustc_front::util::{is_comparison_binop, binop_to_string};
|
||||
use syntax::ast::{IntTy, UintTy, FloatTy};
|
||||
|
||||
use syntax::codemap::Span;
|
||||
use utils::*;
|
||||
|
||||
/// Handles all the linting of funky types
|
||||
@ -618,7 +617,7 @@ enum AbsurdComparisonResult {
|
||||
}
|
||||
|
||||
fn detect_absurd_comparison<'a>(cx: &LateContext, op: BinOp_, lhs: &'a Expr, rhs: &'a Expr)
|
||||
-> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> {
|
||||
-> Option<(ExtremeExpr<'a>, AbsurdComparisonResult)> {
|
||||
use types::ExtremeType::*;
|
||||
use types::AbsurdComparisonResult::*;
|
||||
type Extr<'a> = ExtremeExpr<'a>;
|
||||
@ -704,7 +703,10 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
||||
|
||||
_ => return None,
|
||||
};
|
||||
Some(ExtremeExpr { which: which, expr: expr })
|
||||
Some(ExtremeExpr {
|
||||
which: which,
|
||||
expr: expr,
|
||||
})
|
||||
}
|
||||
|
||||
impl LateLintPass for AbsurdExtremeComparisons {
|
||||
@ -721,16 +723,20 @@ impl LateLintPass for AbsurdExtremeComparisons {
|
||||
let conclusion = match result {
|
||||
AlwaysFalse => "this comparison is always false".to_owned(),
|
||||
AlwaysTrue => "this comparison is always true".to_owned(),
|
||||
InequalityImpossible =>
|
||||
format!("the case where the two sides are not equal never occurs, \
|
||||
consider using {} == {} instead",
|
||||
InequalityImpossible => {
|
||||
format!("the case where the two sides are not equal never occurs, consider using {} == {} \
|
||||
instead",
|
||||
snippet(cx, lhs.span, "lhs"),
|
||||
snippet(cx, rhs.span, "rhs")),
|
||||
snippet(cx, rhs.span, "rhs"))
|
||||
}
|
||||
};
|
||||
|
||||
let help = format!("because {} is the {} value for this type, {}",
|
||||
snippet(cx, culprit.expr.span, "x"),
|
||||
match culprit.which { Minimum => "minimum", Maximum => "maximum" },
|
||||
match culprit.which {
|
||||
Minimum => "minimum",
|
||||
Maximum => "maximum",
|
||||
},
|
||||
conclusion);
|
||||
|
||||
span_help_and_lint(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, &help);
|
||||
|
@ -1,11 +1,8 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use syntax::ast::LitKind;
|
||||
|
||||
use syntax::codemap::Span;
|
||||
use unicode_normalization::UnicodeNormalization;
|
||||
|
||||
use utils::{snippet, span_help_and_lint};
|
||||
|
||||
/// **What it does:** This lint checks for the unicode zero-width space in the code.
|
||||
|
@ -19,11 +19,17 @@ pub struct SpanlessEq<'a, 'tcx: 'a> {
|
||||
|
||||
impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
||||
SpanlessEq { cx: cx, ignore_fn: false }
|
||||
SpanlessEq {
|
||||
cx: cx,
|
||||
ignore_fn: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ignore_fn(self) -> Self {
|
||||
SpanlessEq { cx: self.cx, ignore_fn: true }
|
||||
SpanlessEq {
|
||||
cx: self.cx,
|
||||
ignore_fn: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether two statements are the same.
|
||||
@ -40,7 +46,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
(&StmtExpr(ref l, _), &StmtExpr(ref r, _)) |
|
||||
(&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r),
|
||||
(&StmtSemi(ref l, _), &StmtSemi(ref r, _)) => self.eq_expr(l, r),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -48,7 +54,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
/// Check whether two blocks are the same.
|
||||
pub fn eq_block(&self, left: &Block, right: &Block) -> bool {
|
||||
over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) &&
|
||||
both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
|
||||
both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
|
||||
}
|
||||
|
||||
// ok, it’s a big function, but mostly one big match with simples cases
|
||||
@ -77,9 +83,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
(&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => {
|
||||
lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
|
||||
}
|
||||
(&ExprBlock(ref l), &ExprBlock(ref r)) => {
|
||||
self.eq_block(l, r)
|
||||
}
|
||||
(&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r),
|
||||
(&ExprBinary(lop, ref ll, ref lr), &ExprBinary(rop, ref rl, ref rr)) => {
|
||||
lop.node == rop.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
|
||||
}
|
||||
@ -267,7 +271,10 @@ pub struct SpanlessHash<'a, 'tcx: 'a> {
|
||||
|
||||
impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
||||
SpanlessHash { cx: cx, s: SipHasher::new() }
|
||||
SpanlessHash {
|
||||
cx: cx,
|
||||
s: SipHasher::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(&self) -> u64 {
|
||||
@ -389,7 +396,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
let c: fn(_) -> _ = ExprLit;
|
||||
c.hash(&mut self.s);
|
||||
l.hash(&mut self.s);
|
||||
},
|
||||
}
|
||||
ExprLoop(ref b, ref i) => {
|
||||
let c: fn(_, _) -> _ = ExprLoop;
|
||||
c.hash(&mut self.s);
|
||||
@ -466,7 +473,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
let c: fn(_) -> _ = ExprTup;
|
||||
c.hash(&mut self.s);
|
||||
self.hash_exprs(tup);
|
||||
},
|
||||
}
|
||||
ExprTupField(ref le, li) => {
|
||||
let c: fn(_, _) -> _ = ExprTupField;
|
||||
c.hash(&mut self.s);
|
||||
@ -491,7 +498,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
c.hash(&mut self.s);
|
||||
|
||||
self.hash_exprs(v);
|
||||
},
|
||||
}
|
||||
ExprWhile(ref cond, ref b, l) => {
|
||||
let c: fn(_, _, _) -> _ = ExprWhile;
|
||||
c.hash(&mut self.s);
|
||||
|
@ -9,7 +9,7 @@ use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str::FromStr;
|
||||
use syntax::ast::{LitKind, self};
|
||||
use syntax::ast::{self, LitKind};
|
||||
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ptr::P;
|
||||
|
@ -1,8 +1,7 @@
|
||||
use consts::{Constant, constant_simple, FloatWidth};
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
|
||||
use utils::span_help_and_lint;
|
||||
use consts::{Constant, constant_simple, FloatWidth};
|
||||
|
||||
/// `ZeroDivZeroPass` is a pass that checks for a binary expression that consists
|
||||
/// `of 0.0/0.0`, which is always NaN. It is more clear to replace instances of
|
||||
|
Loading…
Reference in New Issue
Block a user