impl EnumGlobUse {
fn lint_item(&self, cx: &LateContext, item: &Item) {
- if item.vis.node == VisibilityKind::Public {
+ if item.vis.node.is_pub() {
return; // re-exports are fine
}
if let ItemUse(ref path, UseKind::Glob) = item.node {
);
}
}
- if item.vis.node == VisibilityKind::Public {
+ if item.vis.node.is_pub() {
let matching = partial_match(mod_camel, &item_camel);
let rmatching = partial_rmatch(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();
if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node {
if arms[0].pats.len() == 1 {
let good_method = match arms[0].pats[0].node {
- PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => {
- if match_qpath(path, &paths::RESULT_OK) {
- "is_ok()"
- } else if match_qpath(path, &paths::RESULT_ERR) {
- "is_err()"
- } else if match_qpath(path, &paths::OPTION_SOME) {
- "is_some()"
+ PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => {
+ if let PatKind::Wild = pats[0].node {
+ if match_qpath(path, &paths::RESULT_OK) {
+ "is_ok()"
+ } else if match_qpath(path, &paths::RESULT_ERR) {
+ "is_err()"
+ } else if match_qpath(path, &paths::OPTION_SOME) {
+ "is_some()"
+ } else {
+ return;
+ }
} else {
return;
}
use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable,
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt,
- span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then};
+ span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq};
use crate::utils::paths;
/// **What it does:** Checks for for-loops that manually copy items between
if self.state == VarState::DontWarn {
return;
}
- if expr == self.end_expr {
+ if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) {
self.past_loop = true;
return;
}
use rustc::ty;
use syntax::ast;
use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type,
- paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
+ paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq};
/// **What it does:** Checks for mapping `clone()` over an iterator.
///
if clone_call.ident.name == "clone" &&
clone_args.len() == 1 &&
match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) &&
- expr_eq_name(&clone_args[0], arg_ident)
+ expr_eq_name(cx, &clone_args[0], arg_ident)
{
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \
}
}
-fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool {
+fn expr_eq_name(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool {
match expr.node {
ExprPath(QPath::Resolved(None, ref path)) => {
let arg_segment = [
infer_types: true,
},
];
- !path.is_global() && path.segments[..] == arg_segment
+ !path.is_global() && SpanlessEq::new(cx).eq_path_segments(&path.segments[..], &arg_segment)
},
_ => false,
}
fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool {
match expr.node {
ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id),
- _ => expr_eq_name(expr, id),
+ _ => expr_eq_name(cx, expr, id),
}
}
}
fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
- if arms[1].pats[0].node == PatKind::Wild {
+ if is_wild(&arms[1].pats[0]) {
report_single_match_single_pattern(cx, ex, arms, expr, els);
}
}
let path = match arms[1].pats[0].node {
PatKind::TupleStruct(ref path, ref inner, _) => {
// contains any non wildcard patterns? e.g. Err(err)
- if inner.iter().any(|pat| pat.node != PatKind::Wild) {
+ if !inner.iter().all(is_wild) {
return;
}
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))
}
}
+fn is_wild(pat: &impl std::ops::Deref<Target = Pat>) -> bool {
+ match pat.node {
+ PatKind::Wild => true,
+ _ => false,
+ }
+}
+
fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
if match_type(cx, ex_ty, &paths::RESULT) {
let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false));
if_chain! {
if path_str == "Err";
- if inner.iter().any(|pat| pat.node == PatKind::Wild);
+ if inner.iter().any(is_wild);
if let ExprBlock(ref block, _) = arm.body.node;
if is_panic_block(block);
then {
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
- span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
+ span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq};
use crate::utils::paths;
use crate::utils::sugg;
use crate::consts::{constant, Constant};
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
if name == method_name &&
sig.decl.inputs.len() == n_args &&
- out_type.matches(&sig.decl.output) &&
- self_kind.matches(first_arg_ty, first_arg, self_ty, false, &implitem.generics) {
+ out_type.matches(cx, &sig.decl.output) &&
+ self_kind.matches(cx, first_arg_ty, first_arg, self_ty, false, &implitem.generics) {
span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
"defining a method called `{}` on this type; consider implementing \
the `{}` trait or choosing a less ambiguous name", name, trait_name));
if conv.check(&name.as_str());
if !self_kinds
.iter()
- .any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics));
+ .any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics));
then {
- let lint = if item.vis.node == hir::VisibilityKind::Public {
+ let lint = if item.vis.node.is_pub() {
WRONG_PUB_SELF_CONVENTION
} else {
WRONG_SELF_CONVENTION
impl SelfKind {
fn matches(
self,
+ cx: &LateContext,
ty: &hir::Ty,
arg: &hir::Arg,
self_ty: &hir::Ty,
// `Self`, `&mut Self`,
// and `Box<Self>`, including the equivalent types with `Foo`.
- let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty;
+ let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty);
if is_self(arg) {
match self {
SelfKind::Value => is_actually_self(ty),
}
impl OutType {
- fn matches(self, ty: &hir::FunctionRetTy) -> bool {
+ fn matches(self, cx: &LateContext, ty: &hir::FunctionRetTy) -> bool {
+ let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyTup(vec![].into()));
match (self, ty) {
(OutType::Unit, &hir::DefaultReturn(_)) => true,
- (OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true,
+ (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true,
(OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true,
- (OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true,
+ (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true,
(OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)),
_ => false,
}
use syntax::codemap::{ExpnFormat, Span};
use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal,
iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
- span_lint_and_then, walk_ptrs_ty};
+ span_lint_and_then, walk_ptrs_ty, SpanlessEq};
use crate::utils::sugg::Sugg;
use syntax::ast::{LitKind, CRATE_NODE_ID};
use crate::consts::{constant, Constant};
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
if let PatKind::Binding(_, _, ident, Some(ref right)) = pat.node {
- if right.node == PatKind::Wild {
+ if let PatKind::Wild = right.node {
span_lint(
cx,
REDUNDANT_PATTERN,
fn is_used(cx: &LateContext, expr: &Expr) -> bool {
if let Some(parent) = get_parent_expr(cx, expr) {
match parent.node {
- ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr,
+ ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr),
_ => is_used(cx, parent),
}
} else {
.name;
for field in pfields {
- if field.node.pat.node == PatKind::Wild {
+ if let PatKind::Wild = field.node.pat.node {
wilds += 1;
}
}
let mut normal = vec![];
for field in pfields {
- if field.node.pat.node != PatKind::Wild {
- if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
+ match field.node.pat.node {
+ PatKind::Wild => {},
+ _ => if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
normal.push(n);
- }
+ },
}
}
for field in pfields {
- if field.node.pat.node == PatKind::Wild {
+ if let PatKind::Wild = field.node.pat.node {
wilds -= 1;
if wilds > 0 {
span_lint(
use rustc::lint::*;
use rustc::hir::*;
-use crate::utils::span_lint;
+use crate::utils::{span_lint, SpanlessEq};
/// **What it does:** Detects classic underflow/overflow checks.
///
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional {
// a + b < a, a > a + b, a < a - b, a - b > a
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
+ let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r);
if_chain! {
if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node;
if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node;
- if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0];
+ if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
if cx.tables.expr_ty(ident1).is_integral();
if cx.tables.expr_ty(ident2).is_integral();
then {
if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node;
- if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0];
+ if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
if cx.tables.expr_ty(ident1).is_integral();
if cx.tables.expr_ty(ident2).is_integral();
then {
use syntax::ast::RangeLimits;
use syntax::codemap::Spanned;
use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then};
-use crate::utils::{get_trait_def_id, higher, implements_trait};
+use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::sugg::Sugg;
/// **What it does:** Checks for calling `.step_by(0)` on iterators,
// .iter() and .len() called on same Path
if let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node;
if let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node;
- if iter_path.segments == len_path.segments;
+ if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
then {
span_lint(cx,
RANGE_ZIP_WITH_LEN,
})
},
(&ExprMethodCall(ref l_path, _, ref l_args), &ExprMethodCall(ref r_path, _, ref r_args)) => {
- !self.ignore_fn && l_path == r_path && self.eq_exprs(l_args, r_args)
+ !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
},
(&ExprRepeat(ref le, ref ll_id), &ExprRepeat(ref re, ref rl_id)) => {
let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body));
}
}
- fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool {
+ pub fn eq_path_segments(&mut self, left: &[PathSegment], right: &[PathSegment]) -> bool {
+ left.len() == right.len() && left.iter().zip(right).all(|(l, r)| self.eq_path_segment(l, r))
+ }
+
+ pub fn eq_path_segment(&mut self, left: &PathSegment, right: &PathSegment) -> bool {
// The == of idents doesn't work with different contexts,
// we have to be explicit about hygiene
if left.ident.as_str() != right.ident.as_str() {
}
}
- fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool {
- match (&left.node, &right.node) {
+ pub fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool {
+ self.eq_ty_kind(&left.node, &right.node)
+ }
+
+ pub fn eq_ty_kind(&mut self, left: &Ty_, right: &Ty_) -> bool {
+ match (left, right) {
(&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyArray(ref lt, ref ll_id), &TyArray(ref rt, ref rl_id)) => {
let full_table = self.tables;
self.hash_expr(e);
}
- b.rules.hash(&mut self.s);
+ match b.rules {
+ BlockCheckMode::DefaultBlock => 0,
+ BlockCheckMode::UnsafeBlock(_) => 1,
+ BlockCheckMode::PushUnsafeBlock(_) => 2,
+ BlockCheckMode::PopUnsafeBlock(_) => 3,
+ }.hash(&mut self.s);
}
#[allow(many_single_char_names)]
ExprClosure(cap, _, eid, _, _) => {
let c: fn(_, _, _, _, _) -> _ = ExprClosure;
c.hash(&mut self.s);
- cap.hash(&mut self.s);
+ match cap {
+ CaptureClause::CaptureByValue => 0,
+ CaptureClause::CaptureByRef => 1,
+ }.hash(&mut self.s);
self.hash_expr(&self.cx.tcx.hir.body(eid).value);
},
ExprField(ref e, ref f) => {
if let ItemStatic(ref ty, MutImmutable, body_id) = item.node {
if is_lint_ref_type(ty) {
self.declared_lints.insert(item.name, item.span);
- } else if is_lint_array_type(ty) && item.vis.node == VisibilityKind::Inherited && item.name == "ARRAY" {
- let mut collector = LintCollector {
- output: &mut self.registered_lints,
- cx,
- };
- collector.visit_expr(&cx.tcx.hir.body(body_id).value);
+ } else if is_lint_array_type(ty) && item.name == "ARRAY" {
+ if let VisibilityKind::Inherited = item.vis.node {
+ let mut collector = LintCollector {
+ output: &mut self.registered_lints,
+ cx,
+ };
+ collector.visit_expr(&cx.tcx.hir.body(body_id).value);
+ }
}
}
}