Use symbols instead of strings

This commit is contained in:
Oliver Scherer 2019-05-14 01:34:08 +02:00
parent 42480fd031
commit b2dbda4d48
82 changed files with 1206 additions and 700 deletions

View File

@ -1,10 +1,13 @@
use crate::utils::span_lint;
use crate::utils::sym;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use std::f64::consts as f64;
use syntax::ast::{FloatTy, Lit, LitKind};
use syntax::ast::{FloatTy, LitKind};
use syntax::symbol;
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
declare_clippy_lint! {
/// **What it does:** Checks for floating point literals that approximate
@ -30,25 +33,27 @@ declare_clippy_lint! {
"the approximate of a known float constant (in `std::fXX::consts`)"
}
lazy_static! {
// Tuples are of the form (constant, name, min_digits)
const KNOWN_CONSTS: &[(f64, &str, usize)] = &[
(f64::E, "E", 4),
(f64::FRAC_1_PI, "FRAC_1_PI", 4),
(f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),
(f64::FRAC_2_PI, "FRAC_2_PI", 5),
(f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5),
(f64::FRAC_PI_2, "FRAC_PI_2", 5),
(f64::FRAC_PI_3, "FRAC_PI_3", 5),
(f64::FRAC_PI_4, "FRAC_PI_4", 5),
(f64::FRAC_PI_6, "FRAC_PI_6", 5),
(f64::FRAC_PI_8, "FRAC_PI_8", 5),
(f64::LN_10, "LN_10", 5),
(f64::LN_2, "LN_2", 5),
(f64::LOG10_E, "LOG10_E", 5),
(f64::LOG2_E, "LOG2_E", 5),
(f64::PI, "PI", 3),
(f64::SQRT_2, "SQRT_2", 5),
static ref KNOWN_CONSTS: [(f64, Symbol, usize); 16] = [
(f64::E, *sym::E, 4),
(f64::FRAC_1_PI, *sym::FRAC_1_PI, 4),
(f64::FRAC_1_SQRT_2, *sym::FRAC_1_SQRT_2, 5),
(f64::FRAC_2_PI, *sym::FRAC_2_PI, 5),
(f64::FRAC_2_SQRT_PI, *sym::FRAC_2_SQRT_PI, 5),
(f64::FRAC_PI_2, *sym::FRAC_PI_2, 5),
(f64::FRAC_PI_3, *sym::FRAC_PI_3, 5),
(f64::FRAC_PI_4, *sym::FRAC_PI_4, 5),
(f64::FRAC_PI_6, *sym::FRAC_PI_6, 5),
(f64::FRAC_PI_8, *sym::FRAC_PI_8, 5),
(f64::LN_10, *sym::LN_10, 5),
(f64::LN_2, *sym::LN_2, 5),
(f64::LOG10_E, *sym::LOG10_E, 5),
(f64::LOG2_E, *sym::LOG2_E, 5),
(f64::PI, *sym::PI, 3),
(f64::SQRT_2, *sym::SQRT_2, 5),
];
}
declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
@ -72,7 +77,7 @@ fn check_lit(cx: &LateContext<'_, '_>, lit: &LitKind, e: &Expr) {
fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) {
let s = s.as_str();
if s.parse::<f64>().is_ok() {
for &(constant, name, min_digits) in KNOWN_CONSTS {
for &(constant, name, min_digits) in KNOWN_CONSTS.iter() {
if is_approx_const(constant, &s, min_digits) {
span_lint(
cx,

View File

@ -6,6 +6,7 @@ use syntax_pos::Span;
use crate::consts::{constant, Constant};
use crate::utils::{in_macro_or_desugar, is_direct_expn_of, span_help_and_lint};
use crate::utils::sym;
declare_clippy_lint! {
/// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
@ -40,9 +41,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
!in_macro_or_desugar(span)
};
if_chain! {
if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
if let Some(assert_span) = is_direct_expn_of(e.span, *sym::assert);
if !in_macro_or_desugar(assert_span)
|| is_direct_expn_of(assert_span, "debug_assert")
|| is_direct_expn_of(assert_span, *sym::debug_assert)
.map_or(false, debug_assert_not_in_macro_or_desugar);
if let ExprKind::Unary(_, ref lit) = e.node;
if let Some(bool_const) = constant(cx, cx.tables, lit);

View File

@ -9,6 +9,7 @@ use crate::utils::{
get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method, SpanlessEq,
};
use crate::utils::{higher, sugg};
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
@ -88,8 +89,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
$($trait_name:ident),+) => {
match $op {
$(hir::BinOpKind::$trait_name => {
let [krate, module] = crate::utils::paths::OPS_MODULE;
let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
let [krate, module] = *crate::utils::paths::OPS_MODULE;
let ident = {
*crate::utils::sym::assign::$trait_name
};
let path: [Symbol; 3] = [krate, module, ident];
let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
trait_id
} else {

View File

@ -3,8 +3,9 @@
use crate::reexport::*;
use crate::utils::{
in_macro_or_desugar, is_present_in_source, last_line_of_span, paths, snippet_opt, span_lint, span_lint_and_sugg,
span_lint_and_then, without_block_comments,
span_lint_and_then, without_block_comments, match_def_path
};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{
@ -17,6 +18,7 @@ use rustc_errors::Applicability;
use semver::Version;
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use syntax::source_map::Span;
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Checks for items annotated with `#[inline(always)]`,
@ -205,14 +207,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes {
},
_ => {},
}
if items.is_empty() || !attr.check_name("deprecated") {
if items.is_empty() || !attr.check_name(*sym::deprecated) {
return;
}
for item in items {
if_chain! {
if let NestedMetaItem::MetaItem(mi) = &item;
if let MetaItemKind::NameValue(lit) = &mi.node;
if mi.check_name("since");
if mi.check_name(*sym::since);
then {
check_semver(cx, item.span(), lit);
}
@ -228,7 +230,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes {
}
match item.node {
ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
let skip_unused_imports = item.attrs.iter().any(|attr| attr.check_name("macro_use"));
let skip_unused_imports = item.attrs.iter().any(|attr| attr.check_name(*sym::macro_use));
for attr in &item.attrs {
if in_external_macro(cx.sess(), attr.span) {
@ -243,15 +245,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes {
for lint in lint_list {
match item.node {
ItemKind::Use(..) => {
if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
if is_word(lint, *sym::unused_imports) || is_word(lint, *sym::deprecated) {
return;
}
},
ItemKind::ExternCrate(..) => {
if is_word(lint, "unused_imports") && skip_unused_imports {
if is_word(lint, *sym::unused_imports) && skip_unused_imports {
return;
}
if is_word(lint, "unused_extern_crates") {
if is_word(lint, *sym::unused_extern_crates) {
return;
}
},
@ -395,7 +397,7 @@ fn is_relevant_expr(cx: &LateContext<'_, '_>, tables: &ty::TypeckTables<'_>, exp
ExprKind::Call(path_expr, _) => {
if let ExprKind::Path(qpath) = &path_expr.node {
if let Some(fun_id) = tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
!cx.match_def_path(fun_id, &paths::BEGIN_PANIC)
!match_def_path(cx, fun_id, &*paths::BEGIN_PANIC)
} else {
true
}
@ -441,10 +443,10 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib
}
if let Some(values) = attr.meta_item_list() {
if values.len() != 1 || !attr.check_name("inline") {
if values.len() != 1 || !attr.check_name(*sym::inline) {
continue;
}
if is_word(&values[0], "always") {
if is_word(&values[0], *sym::always) {
span_lint(
cx,
INLINE_ALWAYS,
@ -473,7 +475,7 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
);
}
fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool {
if let NestedMetaItem::MetaItem(mi) = &nmi {
mi.is_word() && mi.check_name(expected)
} else {
@ -487,16 +489,16 @@ impl EarlyLintPass for DeprecatedCfgAttribute {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
if_chain! {
// check cfg_attr
if attr.check_name("cfg_attr");
if attr.check_name(*sym::cfg_attr);
if let Some(items) = attr.meta_item_list();
if items.len() == 2;
// check for `rustfmt`
if let Some(feature_item) = items[0].meta_item();
if feature_item.check_name("rustfmt");
if feature_item.check_name(*sym::rustfmt);
// check for `rustfmt_skip` and `rustfmt::skip`
if let Some(skip_item) = &items[1].meta_item();
if skip_item.check_name("rustfmt_skip") ||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == "skip";
if skip_item.check_name(*sym::rustfmt_skip) ||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == *sym::skip;
// Only lint outer attributes, because custom inner attributes are unstable
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
if let AttrStyle::Outer = attr.style;

View File

@ -2,6 +2,7 @@ use crate::utils::{
get_trait_def_id, implements_trait, in_macro, in_macro_or_desugar, match_type, paths, snippet_opt,
span_lint_and_then, SpanlessEq,
};
use crate::utils::sym;
use rustc::hir::intravisit::*;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -10,6 +11,8 @@ use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Applicability;
use syntax::ast::LitKind;
use syntax::source_map::{dummy_spanned, Span, DUMMY_SP};
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
declare_clippy_lint! {
/// **What it does:** Checks for boolean expressions that can be written more
@ -49,8 +52,13 @@ declare_clippy_lint! {
"boolean expressions that contain terminals which can be eliminated"
}
lazy_static! {
// For each pairs, both orders are considered.
const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")];
static ref METHODS_WITH_NEGATION: [(Symbol, Symbol); 2] = [
(*sym::is_some, *sym::is_none),
(*sym::is_err, *sym::is_ok),
];
}
declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, LOGIC_BUG]);
@ -187,8 +195,8 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
},
ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
let type_of_receiver = self.cx.tables.expr_ty(&args[0]);
if !match_type(self.cx, type_of_receiver, &paths::OPTION)
&& !match_type(self.cx, type_of_receiver, &paths::RESULT)
if !match_type(self.cx, type_of_receiver, &*paths::OPTION)
&& !match_type(self.cx, type_of_receiver, &*paths::RESULT)
{
return None;
}
@ -196,7 +204,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
.iter()
.cloned()
.flat_map(|(a, b)| vec![(a, b), (b, a)])
.find(|&(a, _)| a == path.ident.as_str())
.find(|&(a, _)| a == path.ident.name)
.and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method)))
},
_ => None,
@ -466,5 +474,5 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> bool {
let ty = cx.tables.expr_ty(expr);
get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]))
get_trait_def_id(cx, &*paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]))
}

View File

@ -2,6 +2,7 @@ use crate::utils::{
contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability,
span_lint_and_sugg, walk_ptrs_ty,
};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -37,10 +38,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
if_chain! {
if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
if count.ident.name == "count";
if count.ident.name == *sym::count;
if count_args.len() == 1;
if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
if filter.ident.name == "filter";
if filter.ident.name == *sym::filter;
if filter_args.len() == 2;
if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
then {
@ -52,7 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
if op.node == BinOpKind::Eq;
if match_type(cx,
walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
&paths::SLICE_ITER);
&*paths::SLICE_ITER);
then {
let needle = match get_path_name(l) {
Some(name) if check_arg(name, argname, r) => r,
@ -67,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
filter_args[0].node {
let p = path.ident.name;
if (p == "iter" || p == "iter_mut") && args.len() == 1 {
if (p == *sym::iter || p == *sym::iter_mut) && args.len() == 1 {
&args[0]
} else {
&filter_args[0]

View File

@ -9,6 +9,7 @@ use rustc::{declare_tool_lint, impl_lint_pass};
use syntax::ast::Attribute;
use syntax::source_map::Span;
use crate::utils::sym;
use crate::utils::{in_macro_or_desugar, is_allowed, match_type, paths, span_help_and_lint, LimitStack};
declare_clippy_lint! {
@ -71,7 +72,7 @@ impl CognitiveComplexity {
..
} = helper;
let ret_ty = cx.tables.node_type(expr.hir_id);
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
let ret_adjust = if match_type(cx, ret_ty, &*paths::RESULT) {
returns
} else {
returns / 2
@ -118,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity {
hir_id: HirId,
) {
let def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id);
if !cx.tcx.has_attr(def_id, "test") {
if !cx.tcx.has_attr(def_id, *sym::test) {
self.check(cx, body, span);
}
}

View File

@ -47,7 +47,7 @@ impl StaticConst {
if let Some(lifetime) = *optional_lifetime {
match borrow_type.ty.node {
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
if lifetime.ident.name == "'static" {
if lifetime.ident.name == syntax::symbol::keywords::StaticLifetime.name() {
let snip = snippet(cx, borrow_type.ty.span, "<type>");
let sugg = format!("&{}", snip);
span_lint_and_then(

View File

@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyIterator {
if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node {
let ty = cx.tcx.type_of(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) {
if is_copy(cx, ty) && match_path(&trait_ref.path, &*paths::ITERATOR) {
span_note_and_lint(
cx,
COPY_ITERATOR,

View File

@ -1,4 +1,5 @@
use crate::utils::{snippet_opt, span_help_and_lint, span_lint_and_sugg};
use crate::utils::sym;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
@ -31,7 +32,7 @@ declare_lint_pass!(DbgMacro => [DBG_MACRO]);
impl EarlyLintPass for DbgMacro {
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
if mac.node.path == "dbg" {
if mac.node.path == *sym::dbg {
if let Some(sugg) = tts_span(mac.node.tts.clone()).and_then(|span| snippet_opt(cx, span)) {
span_lint_and_sugg(
cx,

View File

@ -5,7 +5,7 @@ use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use crate::utils::{any_parent_is_automatically_derived, paths, span_lint_and_sugg};
use crate::utils::{any_parent_is_automatically_derived, paths, span_lint_and_sugg, match_def_path};
declare_clippy_lint! {
/// **What it does:** Checks for literal calls to `Default::default()`.
@ -37,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
if let ExprKind::Path(ref qpath) = path.node;
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
if cx.match_def_path(def_id, &paths::DEFAULT_TRAIT_METHOD);
if match_def_path(cx, def_id, &*paths::DEFAULT_TRAIT_METHOD);
then {
match qpath {
QPath::Resolved(..) => {

View File

@ -88,7 +88,7 @@ fn check_hash_peq<'a, 'tcx>(
hash_is_automatically_derived: bool,
) {
if_chain! {
if match_path(&trait_ref.path, &paths::HASH);
if match_path(&trait_ref.path, &*paths::HASH);
if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
then {
// Look for the PartialEq implementations for `ty`
@ -129,7 +129,7 @@ fn check_hash_peq<'a, 'tcx>(
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: Ty<'tcx>) {
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
if match_path(&trait_ref.path, &*paths::CLONE_TRAIT) {
if !is_copy(cx, ty) {
return;
}

View File

@ -1,4 +1,5 @@
use crate::utils::span_lint;
use crate::utils::sym;
use itertools::Itertools;
use pulldown_cmark;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
@ -127,7 +128,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet<String>,
spans.extend_from_slice(&current_spans);
doc.push_str(&current);
}
} else if attr.check_name("doc") {
} else if attr.check_name(*sym::doc) {
// ignore mix of sugared and non-sugared doc
return;
}

View File

@ -1,4 +1,4 @@
use crate::utils::{paths, span_lint};
use crate::utils::{paths, span_lint, match_def_path};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateLintPass, LintArray, LintPass};
@ -56,7 +56,7 @@ fn lint_bound<'a, 'tcx>(cx: &rustc::lint::LateContext<'a, 'tcx>, bound: &'tcx Ge
if_chain! {
if let GenericBound::Trait(t, _) = bound;
if let Some(def_id) = t.trait_ref.path.res.opt_def_id();
if cx.match_def_path(def_id, &paths::DROP_TRAIT);
if match_def_path(cx, def_id, &*paths::DROP_TRAIT);
then {
span_lint(
cx,

View File

@ -1,4 +1,4 @@
use crate::utils::{is_copy, paths, span_note_and_lint};
use crate::utils::{is_copy, paths, span_note_and_lint, match_def_path};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -122,10 +122,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef {
let arg_ty = cx.tables.expr_ty(arg);
if let ty::Ref(..) = arg_ty.sty {
if cx.match_def_path(def_id, &paths::DROP) {
if match_def_path(cx, def_id, &*paths::DROP) {
lint = DROP_REF;
msg = DROP_REF_SUMMARY.to_string();
} else if cx.match_def_path(def_id, &paths::MEM_FORGET) {
} else if match_def_path(cx, def_id, &*paths::MEM_FORGET) {
lint = FORGET_REF;
msg = FORGET_REF_SUMMARY.to_string();
} else {
@ -138,10 +138,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DropForgetRef {
arg.span,
&format!("argument has type {}", arg_ty));
} else if is_copy(cx, arg_ty) {
if cx.match_def_path(def_id, &paths::DROP) {
if match_def_path(cx, def_id, &*paths::DROP) {
lint = DROP_COPY;
msg = DROP_COPY_SUMMARY.to_string();
} else if cx.match_def_path(def_id, &paths::MEM_FORGET) {
} else if match_def_path(cx, def_id, &*paths::MEM_FORGET) {
lint = FORGET_COPY;
msg = FORGET_COPY_SUMMARY.to_string();
} else {

View File

@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.node;
if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.node;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION);
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &*paths::DURATION);
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
then {
let suggested_fn = match (method_path.ident.as_str().as_ref(), divisor) {

View File

@ -1,4 +1,5 @@
use crate::utils::SpanlessEq;
use crate::utils::sym;
use crate::utils::{get_item_name, higher, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty};
use if_chain::if_chain;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@ -91,16 +92,16 @@ fn check_cond<'a, 'tcx, 'b>(
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = check.node;
if params.len() >= 2;
if path.ident.name == "contains_key";
if path.ident.name == *sym::contains_key;
if let ExprKind::AddrOf(_, ref key) = params[1].node;
then {
let map = &params[0];
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map));
return if match_type(cx, obj_ty, &paths::BTREEMAP) {
return if match_type(cx, obj_ty, &*paths::BTREEMAP) {
Some(("BTreeMap", map, key))
}
else if match_type(cx, obj_ty, &paths::HASHMAP) {
else if match_type(cx, obj_ty, &*paths::HASHMAP) {
Some(("HashMap", map, key))
}
else {
@ -126,7 +127,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref params) = expr.node;
if params.len() == 3;
if path.ident.name == "insert";
if path.ident.name == *sym::insert;
if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);
if SpanlessEq::new(self.cx).eq_expr(self.key, &params[1]);
then {

View File

@ -1,4 +1,5 @@
use crate::utils::{is_expn_of, resolve_node, span_lint, span_lint_and_sugg};
use crate::utils::{is_expn_of, resolve_node, span_lint, span_lint_and_sugg, match_def_path};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -31,21 +32,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
if_chain! {
// match call to unwrap
if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node;
if unwrap_fun.ident.name == "unwrap";
if unwrap_fun.ident.name == *sym::unwrap;
// match call to write_fmt
if unwrap_args.len() > 0;
if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
unwrap_args[0].node;
if write_fun.ident.name == "write_fmt";
if write_fun.ident.name == *sym::write_fmt;
// match calls to std::io::stdout() / std::io::stderr ()
if write_args.len() > 0;
if let ExprKind::Call(ref dest_fun, _) = write_args[0].node;
if let ExprKind::Path(ref qpath) = dest_fun.node;
if let Some(dest_fun_id) =
resolve_node(cx, qpath, dest_fun.hir_id).opt_def_id();
if let Some(dest_name) = if cx.match_def_path(dest_fun_id, &["std", "io", "stdio", "stdout"]) {
if let Some(dest_name) = if match_def_path(cx, dest_fun_id, &[*sym::std, *sym::io, *sym::stdio, *sym::stdout]) {
Some("stdout")
} else if cx.match_def_path(dest_fun_id, &["std", "io", "stdio", "stderr"]) {
} else if match_def_path(cx, dest_fun_id, &[*sym::std, *sym::io, *sym::stdio, *sym::stderr]) {
Some("stderr")
} else {
None
@ -54,9 +55,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
let write_span = unwrap_args[0].span;
let calling_macro =
// ordering is important here, since `writeln!` uses `write!` internally
if is_expn_of(write_span, "writeln").is_some() {
if is_expn_of(write_span, *sym::writeln).is_some() {
Some("writeln")
} else if is_expn_of(write_span, "write").is_some() {
} else if is_expn_of(write_span, *sym::write).is_some() {
Some("write")
} else {
None

View File

@ -1,11 +1,13 @@
use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT};
use crate::utils::{is_expn_of, method_chain_args, span_lint_and_then, walk_ptrs_ty};
use crate::utils::{is_expn_of, method_chain_args, span_lint_and_then, walk_ptrs_ty, match_def_path};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::ty::{self, Ty};
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax_pos::Span;
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`
@ -37,7 +39,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom {
if_chain! {
if let hir::ItemKind::Impl(.., ref impl_items) = item.node;
if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
if cx.match_def_path(impl_trait_ref.def_id, &FROM_TRAIT);
if match_def_path(cx, impl_trait_ref.def_id, &*FROM_TRAIT);
then {
lint_impl_body(cx, item.span, impl_items);
}
@ -62,18 +64,18 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
if let ExprKind::Call(ref func_expr, _) = expr.node;
if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.node;
if let Some(path_def_id) = path.res.opt_def_id();
if self.lcx.match_def_path(path_def_id, &BEGIN_PANIC) ||
self.lcx.match_def_path(path_def_id, &BEGIN_PANIC_FMT);
if is_expn_of(expr.span, "unreachable").is_none();
if match_def_path(self.lcx, path_def_id, &*BEGIN_PANIC) ||
match_def_path(self.lcx, path_def_id, &*BEGIN_PANIC_FMT);
if is_expn_of(expr.span, *sym::unreachable).is_none();
then {
self.result.push(expr.span);
}
}
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
if let Some(arglists) = method_chain_args(expr, &[*sym::unwrap]) {
let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0]));
if match_type(self.lcx, reciever_ty, &OPTION) || match_type(self.lcx, reciever_ty, &RESULT) {
if match_type(self.lcx, reciever_ty, &*OPTION) || match_type(self.lcx, reciever_ty, &*RESULT) {
self.result.push(expr.span);
}
}
@ -89,7 +91,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
for impl_item in impl_items {
if_chain! {
if impl_item.ident.name == "from";
if impl_item.ident.name == *sym::from;
if let ImplItemKind::Method(_, body_id) =
cx.tcx.hir().impl_item(impl_item.id).node;
then {
@ -122,9 +124,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
}
}
fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[Symbol]) -> bool {
match ty.sty {
ty::Adt(adt, _) => cx.match_def_path(adt.did, path),
ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
_ => false,
}
}

View File

@ -1,7 +1,8 @@
use crate::utils::paths;
use crate::utils::sym;
use crate::utils::{
in_macro_or_desugar, is_expn_of, last_path_segment, match_type, resolve_node, snippet, span_lint_and_then,
walk_ptrs_ty,
walk_ptrs_ty, match_def_path,
};
use if_chain::if_chain;
use rustc::hir::*;
@ -38,7 +39,7 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessFormat {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Some(span) = is_expn_of(expr.span, "format") {
if let Some(span) = is_expn_of(expr.span, *sym::format) {
if in_macro_or_desugar(span) {
return;
}
@ -48,10 +49,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessFormat {
if_chain! {
if let ExprKind::Path(ref qpath) = fun.node;
if let Some(fun_def_id) = resolve_node(cx, qpath, fun.hir_id).opt_def_id();
let new_v1 = cx.match_def_path(fun_def_id, &paths::FMT_ARGUMENTS_NEWV1);
let new_v1_fmt = cx.match_def_path(
let new_v1 = match_def_path(cx, fun_def_id, &*paths::FMT_ARGUMENTS_NEWV1);
let new_v1_fmt = match_def_path(cx,
fun_def_id,
&paths::FMT_ARGUMENTS_NEWV1FORMATTED
&*paths::FMT_ARGUMENTS_NEWV1FORMATTED
);
if new_v1 || new_v1_fmt;
if check_single_piece(&args[0]);
@ -150,10 +151,10 @@ fn get_single_string_arg<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option
if args.len() == 2;
if let ExprKind::Path(ref qpath) = args[1].node;
if let Some(fun_def_id) = resolve_node(cx, qpath, args[1].hir_id).opt_def_id();
if cx.match_def_path(fun_def_id, &paths::DISPLAY_FMT_METHOD);
if match_def_path(cx, fun_def_id, &*paths::DISPLAY_FMT_METHOD);
then {
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
if ty.sty == ty::Str || match_type(cx, ty, &paths::STRING) {
if ty.sty == ty::Str || match_type(cx, ty, &*paths::STRING) {
if let ExprKind::Tup(ref values) = match_expr.node {
return Some(&values[0]);
}
@ -180,14 +181,14 @@ fn check_unformatted(expr: &Expr) -> bool {
if let ExprKind::Array(ref exprs) = expr.node;
if exprs.len() == 1;
if let ExprKind::Struct(_, ref fields, _) = exprs[0].node;
if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
if let Some(format_field) = fields.iter().find(|f| f.ident.name == *sym::format);
if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node;
if let Some(width_field) = fields.iter().find(|f| f.ident.name == "width");
if let Some(width_field) = fields.iter().find(|f| f.ident.name == *sym::width);
if let ExprKind::Path(ref width_qpath) = width_field.expr.node;
if last_path_segment(width_qpath).ident.name == "Implied";
if let Some(precision_field) = fields.iter().find(|f| f.ident.name == "precision");
if last_path_segment(width_qpath).ident.name == *sym::Implied;
if let Some(precision_field) = fields.iter().find(|f| f.ident.name == *sym::precision);
if let ExprKind::Path(ref precision_path) = precision_field.expr.node;
if last_path_segment(precision_path).ident.name == "Implied";
if last_path_segment(precision_path).ident.name == *sym::Implied;
then {
return true;
}

View File

@ -1,5 +1,6 @@
use crate::utils::{
in_macro_or_desugar, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then,
match_def_path,
};
use crate::utils::{paths, resolve_node};
use rustc::hir::*;
@ -55,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
},
ExprKind::MethodCall(ref name, .., ref args) => {
if match_trait_method(cx, e, &paths::INTO[..]) && &*name.ident.as_str() == "into" {
if match_trait_method(cx, e, &*paths::INTO) && &*name.ident.as_str() == "into" {
let a = cx.tables.expr_ty(e);
let b = cx.tables.expr_ty(&args[0]);
if same_tys(cx, a, b) {
@ -71,7 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
});
}
}
if match_trait_method(cx, e, &paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" {
if match_trait_method(cx, e, &*paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" {
let a = cx.tables.expr_ty(e);
let b = cx.tables.expr_ty(&args[0]);
if same_tys(cx, a, b) {
@ -91,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
ExprKind::Call(ref path, ref args) => {
if let ExprKind::Path(ref qpath) = path.node {
if let Some(def_id) = resolve_node(cx, qpath, path.hir_id).opt_def_id() {
if cx.match_def_path(def_id, &paths::FROM_FROM[..]) {
if match_def_path(cx, def_id, &*paths::FROM_FROM) {
let a = cx.tables.expr_ty(e);
let b = cx.tables.expr_ty(&args[0]);
if same_tys(cx, a, b) {

View File

@ -1,4 +1,5 @@
use crate::utils::{in_macro_or_desugar, is_expn_of, snippet_opt, span_lint_and_then};
use crate::utils::sym;
use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, MatchSource};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -95,7 +96,7 @@ impl ImplicitReturn {
// everything else is missing `return`
_ => {
// make sure it's not just an unreachable expression
if is_expn_of(expr.span, "unreachable").is_none() {
if is_expn_of(expr.span, *sym::unreachable).is_none() {
Self::lint(cx, expr.span, expr.span, "add `return` as shown")
}
},

View File

@ -3,6 +3,9 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
use crate::utils::sym;
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
declare_clippy_lint! {
/// **What it does:** Checks for iteration that is guaranteed to be infinite.
@ -109,32 +112,34 @@ enum Heuristic {
use self::Heuristic::{All, Always, Any, First};
lazy_static! {
/// a slice of (method name, number of args, heuristic, bounds) tuples
/// that will be used to determine whether the method in question
/// returns an infinite or possibly infinite iterator. The finiteness
/// is an upper bound, e.g., some methods can return a possibly
/// infinite iterator at worst, e.g., `take_while`.
static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[
("zip", 2, All, Infinite),
("chain", 2, Any, Infinite),
("cycle", 1, Always, Infinite),
("map", 2, First, Infinite),
("by_ref", 1, First, Infinite),
("cloned", 1, First, Infinite),
("rev", 1, First, Infinite),
("inspect", 1, First, Infinite),
("enumerate", 1, First, Infinite),
("peekable", 2, First, Infinite),
("fuse", 1, First, Infinite),
("skip", 2, First, Infinite),
("skip_while", 1, First, Infinite),
("filter", 2, First, Infinite),
("filter_map", 2, First, Infinite),
("flat_map", 2, First, Infinite),
("unzip", 1, First, Infinite),
("take_while", 2, First, MaybeInfinite),
("scan", 3, First, MaybeInfinite),
static ref HEURISTICS: [(Symbol, usize, Heuristic, Finiteness); 19] = [
(*sym::zip, 2, All, Infinite),
(*sym::chain, 2, Any, Infinite),
(*sym::cycle, 1, Always, Infinite),
(*sym::map, 2, First, Infinite),
(*sym::by_ref, 1, First, Infinite),
(*sym::cloned, 1, First, Infinite),
(*sym::rev, 1, First, Infinite),
(*sym::inspect, 1, First, Infinite),
(*sym::enumerate, 1, First, Infinite),
(*sym::peekable, 2, First, Infinite),
(*sym::fuse, 1, First, Infinite),
(*sym::skip, 2, First, Infinite),
(*sym::skip_while, 1, First, Infinite),
(*sym::filter, 2, First, Infinite),
(*sym::filter_map, 2, First, Infinite),
(*sym::flat_map, 2, First, Infinite),
(*sym::unzip, 1, First, Infinite),
(*sym::take_while, 2, First, MaybeInfinite),
(*sym::scan, 3, First, MaybeInfinite),
];
}
fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
match expr.node {
@ -150,7 +155,7 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
.and(cap);
}
}
if method.ident.name == "flat_map" && args.len() == 2 {
if method.ident.name == *sym::flat_map && args.len() == 2 {
if let ExprKind::Closure(_, _, body_id, _, _) = args[1].node {
let body = cx.tcx.hir().body(body_id);
return is_infinite(cx, &body.value);
@ -162,7 +167,7 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e),
ExprKind::Call(ref path, _) => {
if let ExprKind::Path(ref qpath) = path.node {
match_qpath(qpath, &paths::REPEAT).into()
match_qpath(qpath, &*paths::REPEAT).into()
} else {
Finite
}
@ -172,45 +177,47 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
}
}
lazy_static! {
/// the names and argument lengths of methods that *may* exhaust their
/// iterators
static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[
("find", 2),
("rfind", 2),
("position", 2),
("rposition", 2),
("any", 2),
("all", 2),
static ref POSSIBLY_COMPLETING_METHODS: [(Symbol, usize); 6] = [
(*sym::find, 2),
(*sym::rfind, 2),
(*sym::position, 2),
(*sym::rposition, 2),
(*sym::any, 2),
(*sym::all, 2),
];
/// the names and argument lengths of methods that *always* exhaust
/// their iterators
static COMPLETING_METHODS: &[(&str, usize)] = &[
("count", 1),
("fold", 3),
("for_each", 2),
("partition", 2),
("max", 1),
("max_by", 2),
("max_by_key", 2),
("min", 1),
("min_by", 2),
("min_by_key", 2),
("sum", 1),
("product", 1),
static ref COMPLETING_METHODS: [(Symbol, usize); 12] = [
(*sym::count, 1),
(*sym::fold, 3),
(*sym::for_each, 2),
(*sym::partition, 2),
(*sym::max, 1),
(*sym::max_by, 2),
(*sym::max_by_key, 2),
(*sym::min, 1),
(*sym::min_by, 2),
(*sym::min_by_key, 2),
(*sym::sum, 1),
(*sym::product, 1),
];
/// the paths of types that are known to be infinitely allocating
static INFINITE_COLLECTORS: &[&[&str]] = &[
&paths::BINARY_HEAP,
&paths::BTREEMAP,
&paths::BTREESET,
&paths::HASHMAP,
&paths::HASHSET,
&paths::LINKED_LIST,
&paths::VEC,
&paths::VEC_DEQUE,
static ref INFINITE_COLLECTORS: [Vec<Symbol>; 8] = [
paths::BINARY_HEAP.to_vec(),
paths::BTREEMAP.to_vec(),
paths::BTREESET.to_vec(),
paths::HASHMAP.to_vec(),
paths::HASHSET.to_vec(),
paths::LINKED_LIST.to_vec(),
paths::VEC.to_vec(),
paths::VEC_DEQUE.to_vec(),
];
}
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
match expr.node {
@ -225,13 +232,13 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
return MaybeInfinite.and(is_infinite(cx, &args[0]));
}
}
if method.ident.name == "last" && args.len() == 1 {
let not_double_ended = get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR)
if method.ident.name == *sym::last && args.len() == 1 {
let not_double_ended = get_trait_def_id(cx, &*paths::DOUBLE_ENDED_ITERATOR)
.map_or(false, |id| !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]));
if not_double_ended {
return is_infinite(cx, &args[0]);
}
} else if method.ident.name == "collect" {
} else if method.ident.name == *sym::collect {
let ty = cx.tables.expr_ty(expr);
if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) {
return is_infinite(cx, &args[0]);

View File

@ -2,6 +2,7 @@
use crate::utils::span_lint_and_then;
use crate::utils::sugg::DiagnosticBuilderExt;
use crate::utils::sym;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -40,7 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody {
fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
for attr in attrs {
if !attr.check_name("inline") {
if !attr.check_name(*sym::inline) {
continue;
}

View File

@ -1,4 +1,4 @@
use crate::utils::{paths, span_help_and_lint};
use crate::utils::{paths, span_help_and_lint, match_def_path};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -37,12 +37,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef {
if let ty::Ref(..) = cx.tables.expr_ty(expr).sty;
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
then {
let msg = if cx.match_def_path(def_id, &paths::MEM_ZEROED) |
cx.match_def_path(def_id, &paths::INIT)
let msg = if match_def_path(cx, def_id, &*paths::MEM_ZEROED) |
match_def_path(cx, def_id, &*paths::INIT)
{
ZERO_REF_SUMMARY
} else if cx.match_def_path(def_id, &paths::MEM_UNINIT) |
cx.match_def_path(def_id, &paths::UNINIT)
} else if match_def_path(cx, def_id, &*paths::MEM_UNINIT) |
match_def_path(cx, def_id, &*paths::UNINIT)
{
UNINIT_REF_SUMMARY
} else {

View File

@ -1,6 +1,7 @@
use crate::utils::{
get_item_name, in_macro_or_desugar, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty,
};
use crate::utils::sym;
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -8,8 +9,9 @@ use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use syntax::ast::{Lit, LitKind, Name};
use syntax::ast::{LitKind, Name};
use syntax::source_map::{Span, Spanned};
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Checks for getting the length of something via `.len()`
@ -118,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
}
fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: Symbol) -> bool {
item.ident.name == name
&& if let AssociatedItemKind::Method { has_self } = item.kind {
has_self && {
@ -139,7 +141,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items
}
}
if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, *sym::len)) {
let mut current_and_super_traits = FxHashSet::default();
let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id);
fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);
@ -150,7 +152,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items
.any(|i| {
i.kind == ty::AssociatedKind::Method
&& i.method_has_self_argument
&& i.ident.name == "is_empty"
&& i.ident.name == *sym::is_empty
&& cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
});
@ -169,7 +171,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items
}
fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: Symbol) -> bool {
item.ident.name == name
&& if let AssociatedItemKind::Method { has_self } = item.kind {
has_self && {
@ -181,7 +183,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
}
}
let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, *sym::is_empty)) {
if cx.access_levels.is_exported(is_empty.id.hir_id) {
return;
} else {
@ -191,7 +193,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte
"no corresponding"
};
if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, *sym::len)) {
if cx.access_levels.is_exported(i.id.hir_id) {
let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let ty = cx.tcx.type_of(def_id);
@ -213,7 +215,7 @@ fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op
if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) {
if name == "is_empty" {
if name == *sym::is_empty {
return;
}
}
@ -237,7 +239,7 @@ fn check_len(
return;
}
if method_name == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) {
if method_name == *sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
@ -261,7 +263,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
/// Gets an `AssociatedItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool {
if let ty::AssociatedKind::Method = item.kind {
if item.ident.name == "is_empty" {
if item.ident.name == *sym::is_empty {
let sig = cx.tcx.fn_sig(item.def_id);
let ty = sig.skip_binder();
ty.inputs().len() == 1

View File

@ -6,10 +6,11 @@
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![allow(clippy::missing_docs_in_private_items)]
#![recursion_limit = "256"]
#![recursion_limit = "512"]
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
#![deny(internal)]
#![feature(crate_visibility_modifier)]
#![feature(concat_idents)]
// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)

View File

@ -476,7 +476,7 @@ struct BodyLifetimeChecker {
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
if lifetime.name.ident().name != keywords::Invalid.name() && lifetime.name.ident().name != "'static" {
if lifetime.name.ident().name != keywords::Invalid.name() && lifetime.name.ident().name != syntax::symbol::keywords::StaticLifetime.name() {
self.lifetimes_used_in_body = true;
}
}

View File

@ -12,6 +12,7 @@ use rustc::{declare_lint_pass, declare_tool_lint};
use crate::consts::{constant, Constant};
use crate::utils::usage::mutated_variables;
use crate::utils::{in_macro_or_desugar, sext, sugg};
use crate::utils::sym;
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::cmt_;
use rustc::middle::mem_categorization::Categorization;
@ -554,9 +555,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
{
let iter_expr = &method_args[0];
let lhs_constructor = last_path_segment(qpath);
if method_path.ident.name == "next"
&& match_trait_method(cx, match_expr, &paths::ITERATOR)
&& lhs_constructor.ident.name == "Some"
if method_path.ident.name == *sym::next
&& match_trait_method(cx, match_expr, &*paths::ITERATOR)
&& lhs_constructor.ident.name == *sym::Some
&& (pat_args.is_empty()
|| !is_refutable(cx, &pat_args[0])
&& !is_used_inside(cx, iter_expr, &arms[0].body)
@ -593,7 +594,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
if let StmtKind::Semi(ref expr) = stmt.node {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node {
if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) {
if args.len() == 1 && method.ident.name == *sym::collect && match_trait_method(cx, expr, &*paths::ITERATOR) {
span_lint(
cx,
UNUSED_COLLECT,
@ -811,7 +812,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
_ => false,
};
is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE)
is_slice || match_type(cx, ty, &*paths::VEC) || match_type(cx, ty, &*paths::VEC_DEQUE)
}
fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: HirId) -> Option<FixedOffsetVar> {
@ -874,7 +875,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>(
) -> Option<FixedOffsetVar> {
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node;
if method.ident.name == "clone";
if method.ident.name == *sym::clone;
if args.len() == 1;
if let Some(arg) = args.get(0);
then {
@ -980,7 +981,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
if let Some(end) = *end {
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node;
if method.ident.name == "len";
if method.ident.name == *sym::len;
if len_args.len() == 1;
if let Some(arg) = len_args.get(0);
if snippet(cx, arg.span, "??") == var_name;
@ -1222,7 +1223,7 @@ fn is_len_call(expr: &Expr, var: Name) -> bool {
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.node;
if len_args.len() == 1;
if method.ident.name == "len";
if method.ident.name == *sym::len;
if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].node;
if path.segments.len() == 1;
if path.segments[0].ident.name == var;
@ -1350,7 +1351,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
if is_ref_iterable_type(cx, &args[0]) {
lint_iter_method(cx, args, arg, method_name);
}
} else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) {
} else if method_name == "into_iter" && match_trait_method(cx, arg, &*paths::INTO_ITERATOR) {
let def_id = cx.tables.type_dependent_def_id(arg.hir_id).unwrap();
let substs = cx.tables.node_substs(arg.hir_id);
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
@ -1378,7 +1379,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
applicability,
);
}
} else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) {
} else if method_name == "next" && match_trait_method(cx, arg, &*paths::ITERATOR) {
span_lint(
cx,
ITER_NEXT_LOOP,
@ -1398,7 +1399,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
/// Checks for `for` loops over `Option`s and `Result`s.
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) {
let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) {
if match_type(cx, ty, &*paths::OPTION) {
span_help_and_lint(
cx,
FOR_LOOP_OVER_OPTION,
@ -1414,7 +1415,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) {
snippet(cx, arg.span, "_")
),
);
} else if match_type(cx, ty, &paths::RESULT) {
} else if match_type(cx, ty, &*paths::RESULT) {
span_help_and_lint(
cx,
FOR_LOOP_OVER_RESULT,
@ -1527,7 +1528,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>(
_ => arg,
};
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) {
if match_type(cx, ty, &*paths::HASHMAP) || match_type(cx, ty, &*paths::BTREEMAP) {
span_lint_and_then(
cx,
FOR_KV_MAP,
@ -1807,8 +1808,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if_chain! {
// a range index op
if let ExprKind::MethodCall(ref meth, _, ref args) = expr.node;
if (meth.ident.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if (meth.ident.name == *sym::index && match_trait_method(self.cx, expr, &*paths::INDEX))
|| (meth.ident.name == *sym::index_mut && match_trait_method(self.cx, expr, &*paths::INDEX_MUT));
if !self.check(&args[1], &args[0], expr);
then { return }
}
@ -1963,14 +1964,14 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
// will allow further borrows afterwards
let ty = cx.tables.expr_ty(e);
is_iterable_array(ty, cx) ||
match_type(cx, ty, &paths::VEC) ||
match_type(cx, ty, &paths::LINKED_LIST) ||
match_type(cx, ty, &paths::HASHMAP) ||
match_type(cx, ty, &paths::HASHSET) ||
match_type(cx, ty, &paths::VEC_DEQUE) ||
match_type(cx, ty, &paths::BINARY_HEAP) ||
match_type(cx, ty, &paths::BTREEMAP) ||
match_type(cx, ty, &paths::BTREESET)
match_type(cx, ty, &*paths::VEC) ||
match_type(cx, ty, &*paths::LINKED_LIST) ||
match_type(cx, ty, &*paths::HASHMAP) ||
match_type(cx, ty, &*paths::HASHSET) ||
match_type(cx, ty, &*paths::VEC_DEQUE) ||
match_type(cx, ty, &*paths::BINARY_HEAP) ||
match_type(cx, ty, &*paths::BTREEMAP) ||
match_type(cx, ty, &*paths::BTREESET)
}
fn is_iterable_array(ty: Ty<'_>, cx: &LateContext<'_, '_>) -> bool {
@ -2411,16 +2412,16 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>
if_chain! {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node;
if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].node;
if chain_method.ident.name == "collect" && match_trait_method(cx, &args[0], &paths::ITERATOR);
if chain_method.ident.name == *sym::collect && match_trait_method(cx, &args[0], &*paths::ITERATOR);
if let Some(ref generic_args) = chain_method.args;
if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
then {
let ty = cx.tables.node_type(ty.hir_id);
if match_type(cx, ty, &paths::VEC) ||
match_type(cx, ty, &paths::VEC_DEQUE) ||
match_type(cx, ty, &paths::BTREEMAP) ||
match_type(cx, ty, &paths::HASHMAP) {
if method.ident.name == "len" {
if match_type(cx, ty, &*paths::VEC) ||
match_type(cx, ty, &*paths::VEC_DEQUE) ||
match_type(cx, ty, &*paths::BTREEMAP) ||
match_type(cx, ty, &*paths::HASHMAP) {
if method.ident.name == *sym::len {
let span = shorten_needless_collect_span(expr);
span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| {
db.span_suggestion(
@ -2431,7 +2432,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>
);
});
}
if method.ident.name == "is_empty" {
if method.ident.name == *sym::is_empty {
let span = shorten_needless_collect_span(expr);
span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| {
db.span_suggestion(
@ -2442,7 +2443,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr, cx: &LateContext<'a, 'tcx>
);
});
}
if method.ident.name == "contains" {
if method.ident.name == *sym::contains {
let contains_arg = snippet(cx, args[1].span, "??");
let span = shorten_needless_collect_span(expr);
span_lint_and_then(cx, NEEDLESS_COLLECT, span, NEEDLESS_COLLECT_MSG, |db| {

View File

@ -53,7 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
if args.len() == 2;
if method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]);
if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR);
if match_type(cx, ty, &*paths::OPTION) || match_trait_method(cx, e, &*paths::ITERATOR);
if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node;
let closure_body = cx.tcx.hir().body(body_id);
let closure_expr = remove_blocks(&closure_body.value);
@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
},
hir::ExprKind::MethodCall(ref method, _, ref obj) => {
if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
&& match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
&& match_trait_method(cx, closure_expr, &*paths::CLONE_TRAIT) {
let obj_ty = cx.tables.expr_ty(&obj[0]);
if let ty::Ref(_, ty, _) = obj_ty.sty {

View File

@ -1,4 +1,5 @@
use crate::utils::paths;
use crate::utils::sym;
use crate::utils::{in_macro_or_desugar, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
use if_chain::if_chain;
use rustc::hir;
@ -185,9 +186,9 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) {
let var_arg = &map_args[0];
let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) {
let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &*paths::OPTION) {
("Option", "Some", OPTION_MAP_UNIT_FN)
} else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) {
} else if match_type(cx, cx.tables.expr_ty(var_arg), &*paths::RESULT) {
("Result", "Ok", RESULT_MAP_UNIT_FN)
} else {
return;
@ -245,7 +246,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapUnit {
}
if let hir::StmtKind::Semi(ref expr) = stmt.node {
if let Some(arglists) = method_chain_args(expr, &["map"]) {
if let Some(arglists) = method_chain_args(expr, &[*sym::map]) {
lint_map_unit_fn(cx, stmt, expr, arglists[0]);
}
}

View File

@ -1,5 +1,6 @@
use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::sym;
use crate::utils::sugg::Sugg;
use crate::utils::{
expr_block, in_macro_or_desugar, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks,
@ -319,13 +320,13 @@ fn check_single_match_opt_like(
) {
// list of candidate `Enum`s we know will never get any more members
let candidates = &[
(&paths::COW, "Borrowed"),
(&paths::COW, "Cow::Borrowed"),
(&paths::COW, "Cow::Owned"),
(&paths::COW, "Owned"),
(&paths::OPTION, "None"),
(&paths::RESULT, "Err"),
(&paths::RESULT, "Ok"),
(&*paths::COW, "Borrowed"),
(&*paths::COW, "Cow::Borrowed"),
(&*paths::COW, "Cow::Owned"),
(&*paths::COW, "Owned"),
(&*paths::OPTION, "None"),
(&*paths::RESULT, "Err"),
(&*paths::RESULT, "Ok"),
];
let path = match arms[1].pats[0].node {
@ -436,7 +437,7 @@ fn is_wild(pat: &impl std::ops::Deref<Target = Pat>) -> bool {
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) {
if match_type(cx, ex_ty, &*paths::RESULT) {
for arm in arms {
if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pats[0].node {
let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false));
@ -552,10 +553,10 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
fn is_panic_block(block: &Block) -> bool {
match (&block.expr, block.stmts.len(), block.stmts.first()) {
(&Some(ref exp), 0, _) => {
is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none()
is_expn_of(exp.span, *sym::panic).is_some() && is_expn_of(exp.span, *sym::unreachable).is_none()
},
(&None, 1, Some(stmt)) => {
is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
is_expn_of(stmt.span, *sym::panic).is_some() && is_expn_of(stmt.span, *sym::unreachable).is_none()
},
_ => false,
}
@ -717,7 +718,7 @@ fn is_unit_expr(expr: &Expr) -> bool {
// Checks if arm has the form `None => None`
fn is_none_arm(arm: &Arm) -> bool {
match arm.pats[0].node {
PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => true,
PatKind::Path(ref path) if match_qpath(path, &*paths::OPTION_NONE) => true,
_ => false,
}
}
@ -726,12 +727,12 @@ fn is_none_arm(arm: &Arm) -> bool {
fn is_ref_some_arm(arm: &Arm) -> Option<BindingAnnotation> {
if_chain! {
if let PatKind::TupleStruct(ref path, ref pats, _) = arm.pats[0].node;
if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME);
if pats.len() == 1 && match_qpath(path, &*paths::OPTION_SOME);
if let PatKind::Binding(rb, .., ident, _) = pats[0].node;
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).node;
if let ExprKind::Path(ref some_path) = e.node;
if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1;
if match_qpath(some_path, &*paths::OPTION_SOME) && args.len() == 1;
if let ExprKind::Path(ref qpath) = args[0].node;
if let &QPath::Resolved(_, ref path2) = qpath;
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;

View File

@ -1,4 +1,4 @@
use crate::utils::{paths, snippet, span_lint_and_then, walk_ptrs_ty_depth};
use crate::utils::{paths, snippet, span_lint_and_then, walk_ptrs_ty_depth, match_def_path};
use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant {
// is `mem::discriminant`
if let ExprKind::Path(ref func_qpath) = func.node;
if let Some(def_id) = cx.tables.qpath_res(func_qpath, func.hir_id).opt_def_id();
if cx.match_def_path(def_id, &paths::MEM_DISCRIMINANT);
if match_def_path(cx, def_id, &*paths::MEM_DISCRIMINANT);
// type is non-enum
let ty_param = cx.tables.node_substs(func.hir_id).type_at(0);
if !ty_param.is_enum();

View File

@ -1,4 +1,4 @@
use crate::utils::{paths, span_lint};
use crate::utils::{paths, span_lint, match_def_path};
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -28,7 +28,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget {
if let ExprKind::Call(ref path_expr, ref args) = e.node {
if let ExprKind::Path(ref qpath) = path_expr.node {
if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
if cx.match_def_path(def_id, &paths::MEM_FORGET) {
if match_def_path(cx, def_id, &*paths::MEM_FORGET) {
let forgot_ty = cx.tables.expr_ty(&args[0]);
if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {

View File

@ -1,4 +1,4 @@
use crate::utils::{match_qpath, paths, snippet_with_applicability, span_lint_and_sugg};
use crate::utils::{match_qpath, paths, snippet_with_applicability, span_lint_and_sugg, match_def_path};
use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind, MutMutable, QPath};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -42,11 +42,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
if func_args.len() == 2;
if let ExprKind::Path(ref func_qpath) = func.node;
if let Some(def_id) = cx.tables.qpath_res(func_qpath, func.hir_id).opt_def_id();
if cx.match_def_path(def_id, &paths::MEM_REPLACE);
if match_def_path(cx, def_id, &*paths::MEM_REPLACE);
// Check that second argument is `Option::None`
if let ExprKind::Path(ref replacement_qpath) = func_args[1].node;
if match_qpath(replacement_qpath, &paths::OPTION_NONE);
if match_qpath(replacement_qpath, &*paths::OPTION_NONE);
then {
// Since this is a late pass (already type-checked),

View File

@ -15,16 +15,19 @@ use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast;
use syntax::source_map::{BytePos, Span};
use syntax::symbol::LocalInternedString;
use syntax::symbol::{LocalInternedString, Symbol};
use lazy_static::lazy_static;
use crate::utils::paths;
use crate::utils::sugg;
use crate::utils::sym;
use crate::utils::{
get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, implements_trait, in_macro, is_copy,
is_ctor_function, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_path, match_qpath,
match_trait_method, match_type, match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys,
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
match_def_path,
};
declare_clippy_lint! {
@ -905,20 +908,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
let self_ty = cx.tables.expr_ty_adjusted(&args[0]);
if args.len() == 1 && method_call.ident.name == "clone" {
if args.len() == 1 && method_call.ident.name == *sym::clone {
lint_clone_on_copy(cx, expr, &args[0], self_ty);
lint_clone_on_ref_ptr(cx, expr, &args[0]);
}
match self_ty.sty {
ty::Ref(_, ty, _) if ty.sty == ty::Str => {
for &(method, pos) in &PATTERN_METHODS {
for &(method, pos) in PATTERN_METHODS.iter() {
if method_call.ident.name == method && args.len() > pos {
lint_single_char_pattern(cx, expr, &args[pos]);
}
}
},
ty::Ref(..) if method_call.ident.name == "into_iter" => {
ty::Ref(..) if method_call.ident.name == *sym::into_iter => {
lint_into_iter(cx, expr, self_ty, *method_span);
},
_ => (),
@ -956,7 +959,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
then {
if cx.access_levels.is_exported(implitem.hir_id) {
// check missing trait implementations
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
for &(method_name, n_args, self_kind, out_type, trait_name) in TRAIT_METHODS.iter() {
if name == method_name &&
sig.decl.inputs.len() == n_args &&
out_type.matches(cx, &sig.decl.output) &&
@ -1030,7 +1033,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
}
}
if name == "new" && !same_tys(cx, ret_ty, ty) {
if name == *sym::new && !same_tys(cx, ret_ty, ty) {
span_lint(
cx,
NEW_RET_NO_SELF,
@ -1065,7 +1068,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
if ["default", "new"].contains(&path) {
let arg_ty = cx.tables.expr_ty(arg);
let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) {
let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &*paths::DEFAULT_TRAIT) {
default_trait_id
} else {
return false;
@ -1108,10 +1111,10 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
) {
// (path, fn_has_argument, methods, suffix)
let know_types: &[(&[_], _, &[_], _)] = &[
(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
(&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
(&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
(&paths::RESULT, true, &["or", "unwrap_or"], "else"),
(&*paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
(&*paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
(&*paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
(&*paths::RESULT, true, &["or", "unwrap_or"], "else"),
];
// early check if the name is one we care about
@ -1206,11 +1209,11 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
hir::ExprKind::AddrOf(_, expr) => expr,
hir::ExprKind::MethodCall(method_name, _, call_args) => {
if call_args.len() == 1
&& (method_name.ident.name == "as_str" || method_name.ident.name == "as_ref")
&& (method_name.ident.name == *sym::as_str || method_name.ident.name == *sym::as_ref)
&& {
let arg_type = cx.tables.expr_ty(&call_args[0]);
let base_type = walk_ptrs_ty(arg_type);
base_type.sty == ty::Str || match_type(cx, base_type, &paths::STRING)
base_type.sty == ty::Str || match_type(cx, base_type, &*paths::STRING)
}
{
&call_args[0]
@ -1228,7 +1231,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
// converted to string.
fn requires_to_string(cx: &LateContext<'_, '_>, arg: &hir::Expr) -> bool {
let arg_ty = cx.tables.expr_ty(arg);
if match_type(cx, arg_ty, &paths::STRING) {
if match_type(cx, arg_ty, &*paths::STRING) {
return false;
}
if let ty::Ref(ty::ReStatic, ty, ..) = arg_ty.sty {
@ -1277,9 +1280,9 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
}
let receiver_type = cx.tables.expr_ty(&args[0]);
let closure_args = if match_type(cx, receiver_type, &paths::OPTION) {
let closure_args = if match_type(cx, receiver_type, &*paths::OPTION) {
"||"
} else if match_type(cx, receiver_type, &paths::RESULT) {
} else if match_type(cx, receiver_type, &*paths::RESULT) {
"|_|"
} else {
return;
@ -1293,7 +1296,7 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
//Special handling for `format!` as arg_root
if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg_root.node {
if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 {
if is_expn_of(inner_fun.span, *sym::format).is_some() && inner_args.len() == 1 {
if let hir::ExprKind::Call(_, format_args) = &inner_args[0].node {
let fmt_spec = &format_args[0];
let fmt_args = &format_args[1];
@ -1433,11 +1436,11 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg));
if let ty::Adt(_, subst) = obj_ty.sty {
let caller_type = if match_type(cx, obj_ty, &paths::RC) {
let caller_type = if match_type(cx, obj_ty, &*paths::RC) {
"Rc"
} else if match_type(cx, obj_ty, &paths::ARC) {
} else if match_type(cx, obj_ty, &*paths::ARC) {
"Arc"
} else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) {
} else if match_type(cx, obj_ty, &*paths::WEAK_RC) || match_type(cx, obj_ty, &*paths::WEAK_ARC) {
"Weak"
} else {
return;
@ -1462,12 +1465,12 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::
fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
let arg = &args[1];
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
if let Some(arglists) = method_chain_args(arg, &[*sym::chars]) {
let target = &arglists[0][0];
let self_ty = walk_ptrs_ty(cx.tables.expr_ty(target));
let ref_str = if self_ty.sty == ty::Str {
""
} else if match_type(cx, self_ty, &paths::STRING) {
} else if match_type(cx, self_ty, &*paths::STRING) {
"&"
} else {
return;
@ -1493,7 +1496,7 @@ fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::E
fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
if match_type(cx, obj_ty, &paths::STRING) {
if match_type(cx, obj_ty, &*paths::STRING) {
lint_string_extend(cx, expr, args);
}
}
@ -1504,7 +1507,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Ex
if args.len() == 1;
if let hir::ExprKind::Path(ref path) = fun.node;
if let Res::Def(DefKind::Method, did) = cx.tables.qpath_res(path, fun.hir_id);
if cx.match_def_path(did, &paths::CSTRING_NEW);
if match_def_path(cx, did, &*paths::CSTRING_NEW);
then {
span_lint_and_then(
cx,
@ -1520,7 +1523,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Ex
}
fn lint_iter_cloned_collect<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, iter_args: &'tcx [hir::Expr]) {
if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) {
if match_type(cx, cx.tables.expr_ty(expr), &*paths::VEC) {
if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])) {
if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()) {
span_lint_and_sugg(
@ -1598,7 +1601,7 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args:
}
// Check that this is a call to Iterator::fold rather than just some function called fold
if !match_trait_method(cx, expr, &paths::ITERATOR) {
if !match_trait_method(cx, expr, &*paths::ITERATOR) {
return;
}
@ -1624,9 +1627,9 @@ fn lint_iter_nth<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, iter_ar
let mut_str = if is_mut { "_mut" } else { "" };
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() {
"slice"
} else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC) {
} else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &*paths::VEC) {
"Vec"
} else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
} else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &*paths::VEC_DEQUE) {
"VecDeque"
} else {
return; // caller is not a type that we want to lint
@ -1657,16 +1660,16 @@ fn lint_get_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, get_a
let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
needs_ref = get_args_str.parse::<usize>().is_ok();
"slice"
} else if match_type(cx, expr_ty, &paths::VEC) {
} else if match_type(cx, expr_ty, &*paths::VEC) {
needs_ref = get_args_str.parse::<usize>().is_ok();
"Vec"
} else if match_type(cx, expr_ty, &paths::VEC_DEQUE) {
} else if match_type(cx, expr_ty, &*paths::VEC_DEQUE) {
needs_ref = get_args_str.parse::<usize>().is_ok();
"VecDeque"
} else if !is_mut && match_type(cx, expr_ty, &paths::HASHMAP) {
} else if !is_mut && match_type(cx, expr_ty, &*paths::HASHMAP) {
needs_ref = true;
"HashMap"
} else if !is_mut && match_type(cx, expr_ty, &paths::BTREEMAP) {
} else if !is_mut && match_type(cx, expr_ty, &*paths::BTREEMAP) {
needs_ref = true;
"BTreeMap"
} else {
@ -1718,7 +1721,7 @@ fn lint_get_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, get_a
fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) {
// lint if caller of skip is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
span_lint(
cx,
ITER_SKIP_NEXT,
@ -1737,7 +1740,7 @@ fn derefs_to_slice<'a, 'tcx>(
match ty.sty {
ty::Slice(_) => true,
ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
ty::Adt(..) => match_type(cx, ty, &paths::VEC),
ty::Adt(..) => match_type(cx, ty, &*paths::VEC),
ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32,
ty::Ref(_, inner, _) => may_slice(cx, inner),
_ => false,
@ -1745,7 +1748,7 @@ fn derefs_to_slice<'a, 'tcx>(
}
if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.node {
if path.ident.name == "iter" && may_slice(cx, cx.tables.expr_ty(&args[0])) {
if path.ident.name == *sym::iter && may_slice(cx, cx.tables.expr_ty(&args[0])) {
Some(&args[0])
} else {
None
@ -1770,9 +1773,9 @@ fn derefs_to_slice<'a, 'tcx>(
fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::Expr]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
let mess = if match_type(cx, obj_ty, &*paths::OPTION) {
Some((OPTION_UNWRAP_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) {
} else if match_type(cx, obj_ty, &*paths::RESULT) {
Some((RESULT_UNWRAP_USED, "a Result", "Err"))
} else {
None
@ -1796,7 +1799,7 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::E
/// lint use of `ok().expect()` for `Result`s
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) {
// lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT) {
if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &*paths::RESULT) {
let result_type = cx.tables.expr_ty(&ok_args[0]);
if let Some(error_type) = get_error_type(cx, result_type) {
if has_debug_impl(error_type, cx) {
@ -1814,7 +1817,7 @@ fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Ex
/// lint use of `map().flatten()` for `Iterators`
fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr]) {
// lint if caller of `.map().flatten()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `map(..).flatten()` on an `Iterator`. \
This is more succinctly expressed by calling `.flat_map(..)`";
let self_snippet = snippet(cx, map_args[0].span, "..");
@ -1839,8 +1842,8 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
unwrap_args: &'tcx [hir::Expr],
) {
// lint if the caller of `map()` is an `Option`
let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION);
let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT);
let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &*paths::OPTION);
let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &*paths::RESULT);
if is_option || is_result {
// lint message
let msg = if is_option {
@ -1892,10 +1895,10 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
/// lint use of `_.map_or(None, _)` for `Option`s
fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) {
if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) {
if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &*paths::OPTION) {
// check if the first non-self argument to map_or() is None
let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].node {
match_qpath(qpath, &paths::OPTION_NONE)
match_qpath(qpath, &*paths::OPTION_NONE)
} else {
false
};
@ -1922,7 +1925,7 @@ fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr,
/// lint use of `filter().next()` for `Iterators`
fn lint_filter_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) {
// lint if caller of `.filter().next()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
`.find(p)` instead.";
let filter_snippet = snippet(cx, filter_args[1].span, "..");
@ -1950,7 +1953,7 @@ fn lint_filter_map<'a, 'tcx>(
_map_args: &'tcx [hir::Expr],
) {
// lint if caller of `.filter().map()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter(p).map(q)` on an `Iterator`. \
This is more succinctly expressed by calling `.filter_map(..)` instead.";
span_lint(cx, FILTER_MAP, expr.span, msg);
@ -1959,7 +1962,7 @@ fn lint_filter_map<'a, 'tcx>(
/// lint use of `filter_map().next()` for `Iterators`
fn lint_filter_map_next<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, filter_args: &'tcx [hir::Expr]) {
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
`.find_map(p)` instead.";
let filter_snippet = snippet(cx, filter_args[1].span, "..");
@ -1986,7 +1989,7 @@ fn lint_find_map<'a, 'tcx>(
map_args: &'tcx [hir::Expr],
) {
// lint if caller of `.filter().map()` is an Iterator
if match_trait_method(cx, &map_args[0], &paths::ITERATOR) {
if match_trait_method(cx, &map_args[0], &*paths::ITERATOR) {
let msg = "called `find(p).map(q)` on an `Iterator`. \
This is more succinctly expressed by calling `.find_map(..)` instead.";
span_lint(cx, FIND_MAP, expr.span, msg);
@ -2001,7 +2004,7 @@ fn lint_filter_map_map<'a, 'tcx>(
_map_args: &'tcx [hir::Expr],
) {
// lint if caller of `.filter().map()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter_map(p).map(q)` on an `Iterator`. \
This is more succinctly expressed by only calling `.filter_map(..)` instead.";
span_lint(cx, FILTER_MAP, expr.span, msg);
@ -2016,7 +2019,7 @@ fn lint_filter_flat_map<'a, 'tcx>(
_map_args: &'tcx [hir::Expr],
) {
// lint if caller of `.filter().flat_map()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter(p).flat_map(q)` on an `Iterator`. \
This is more succinctly expressed by calling `.flat_map(..)` \
and filtering by returning an empty Iterator.";
@ -2032,7 +2035,7 @@ fn lint_filter_map_flat_map<'a, 'tcx>(
_map_args: &'tcx [hir::Expr],
) {
// lint if caller of `.filter_map().flat_map()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
if match_trait_method(cx, expr, &*paths::ITERATOR) {
let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`. \
This is more succinctly expressed by calling `.flat_map(..)` \
and filtering by returning an empty Iterator.";
@ -2049,7 +2052,7 @@ fn lint_search_is_some<'a, 'tcx>(
is_some_args: &'tcx [hir::Expr],
) {
// lint if caller of search is an Iterator
if match_trait_method(cx, &is_some_args[0], &paths::ITERATOR) {
if match_trait_method(cx, &is_some_args[0], &*paths::ITERATOR) {
let msg = format!(
"called `is_some()` after searching an `Iterator` with {}. This is more succinctly \
expressed by calling `any()`.",
@ -2122,7 +2125,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut Binary
fn lint_chars_cmp(
cx: &LateContext<'_, '_>,
info: &BinaryExprInfo<'_>,
chain_methods: &[&str],
chain_methods: &[Symbol],
lint: &'static Lint,
suggest: &str,
) -> bool {
@ -2132,7 +2135,7 @@ fn lint_chars_cmp(
if arg_char.len() == 1;
if let hir::ExprKind::Path(ref qpath) = fun.node;
if let Some(segment) = single_segment_path(qpath);
if segment.ident.name == "Some";
if segment.ident.name == *sym::Some;
then {
let mut applicability = Applicability::MachineApplicable;
let self_ty = walk_ptrs_ty(cx.tables.expr_ty_adjusted(&args[0][0]));
@ -2164,15 +2167,15 @@ fn lint_chars_cmp(
/// Checks for the `CHARS_NEXT_CMP` lint.
fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with")
lint_chars_cmp(cx, info, &[*sym::chars, *sym::next], CHARS_NEXT_CMP, "starts_with")
}
/// Checks for the `CHARS_LAST_CMP` lint.
fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_LAST_CMP, "ends_with") {
if lint_chars_cmp(cx, info, &[*sym::chars, *sym::last], CHARS_LAST_CMP, "ends_with") {
true
} else {
lint_chars_cmp(cx, info, &["chars", "next_back"], CHARS_LAST_CMP, "ends_with")
lint_chars_cmp(cx, info, &[*sym::chars, *sym::next_back], CHARS_LAST_CMP, "ends_with")
}
}
@ -2180,7 +2183,7 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn
fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
info: &BinaryExprInfo<'_>,
chain_methods: &[&str],
chain_methods: &[Symbol],
lint: &'static Lint,
suggest: &str,
) -> bool {
@ -2213,15 +2216,15 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`.
fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with")
lint_chars_cmp_with_unwrap(cx, info, &[*sym::chars, *sym::next, *sym::unwrap], CHARS_NEXT_CMP, "starts_with")
}
/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`.
fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") {
if lint_chars_cmp_with_unwrap(cx, info, &[*sym::chars, *sym::last, *sym::unwrap], CHARS_LAST_CMP, "ends_with") {
true
} else {
lint_chars_cmp_with_unwrap(cx, info, &["chars", "next_back", "unwrap"], CHARS_LAST_CMP, "ends_with")
lint_chars_cmp_with_unwrap(cx, info, &[*sym::chars, *sym::next_back, *sym::unwrap], CHARS_LAST_CMP, "ends_with")
}
}
@ -2253,7 +2256,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h
fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) {
// when we get here, we've already checked that the call name is "as_ref" or "as_mut"
// check if the call is to the actual `AsRef` or `AsMut` trait
if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) {
if match_trait_method(cx, expr, &*paths::ASREF_TRAIT) || match_trait_method(cx, expr, &*paths::ASMUT_TRAIT) {
// check if the type after `as_ref` or `as_mut` is the same as before
let recvr = &as_ref_args[0];
let rcv_ty = cx.tables.expr_ty(recvr);
@ -2288,11 +2291,12 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_re
fn ty_has_iter_method(
cx: &LateContext<'_, '_>,
self_ref_ty: Ty<'_>,
) -> Option<(&'static Lint, &'static str, &'static str)> {
) -> Option<(&'static Lint, Symbol, &'static str)> {
if let Some(ty_name) = has_iter_method(cx, self_ref_ty) {
let lint = match ty_name {
"array" | "PathBuf" => INTO_ITER_ON_ARRAY,
_ => INTO_ITER_ON_REF,
let lint = if ty_name == *sym::array || ty_name == *sym::PathBuf {
INTO_ITER_ON_ARRAY
} else {
INTO_ITER_ON_REF
};
let mutbl = match self_ref_ty.sty {
ty::Ref(_, _, mutbl) => mutbl,
@ -2309,7 +2313,7 @@ fn ty_has_iter_method(
}
fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_>, method_span: Span) {
if !match_trait_method(cx, expr, &paths::INTO_ITERATOR) {
if !match_trait_method(cx, expr, &*paths::INTO_ITERATOR) {
return;
}
if let Some((lint, kind, method_name)) = ty_has_iter_method(cx, self_ref_ty) {
@ -2331,7 +2335,7 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_
/// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> {
if let ty::Adt(_, substs) = ty.sty {
if match_type(cx, ty, &paths::RESULT) {
if match_type(cx, ty, &*paths::RESULT) {
substs.types().nth(1)
} else {
None
@ -2366,59 +2370,63 @@ const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [
];
#[rustfmt::skip]
const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [
("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"),
("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"),
("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"),
("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"),
("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"),
("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"),
("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"),
("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"),
("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"),
("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"),
("default", 0, SelfKind::No, OutType::Any, "std::default::Default"),
("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"),
("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"),
("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"),
("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"),
("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"),
("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"),
("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"),
("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"),
("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"),
("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"),
("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"),
("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"),
("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"),
("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"),
("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"),
("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"),
("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"),
("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"),
("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"),
lazy_static! {
static ref TRAIT_METHODS: [(Symbol, usize, SelfKind, OutType, &'static str); 30] = [
(*sym::add, 2, SelfKind::Value, OutType::Any, "std::ops::Add"),
(*sym::as_mut, 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"),
(*sym::as_ref, 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"),
(*sym::bitand, 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"),
(*sym::bitor, 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"),
(*sym::bitxor, 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"),
(*sym::borrow, 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"),
(*sym::borrow_mut, 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"),
(*sym::clone, 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"),
(*sym::cmp, 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"),
(*sym::default, 0, SelfKind::No, OutType::Any, "std::default::Default"),
(*sym::deref, 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"),
(*sym::deref_mut, 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"),
(*sym::div, 2, SelfKind::Value, OutType::Any, "std::ops::Div"),
(*sym::drop, 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"),
(*sym::eq, 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"),
(*sym::from_iter, 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"),
(*sym::from_str, 1, SelfKind::No, OutType::Any, "std::str::FromStr"),
(*sym::hash, 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"),
(*sym::index, 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"),
(*sym::index_mut, 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"),
(*sym::into_iter, 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"),
(*sym::mul, 2, SelfKind::Value, OutType::Any, "std::ops::Mul"),
(*sym::neg, 1, SelfKind::Value, OutType::Any, "std::ops::Neg"),
(*sym::next, 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"),
(*sym::not, 1, SelfKind::Value, OutType::Any, "std::ops::Not"),
(*sym::rem, 2, SelfKind::Value, OutType::Any, "std::ops::Rem"),
(*sym::shl, 2, SelfKind::Value, OutType::Any, "std::ops::Shl"),
(*sym::shr, 2, SelfKind::Value, OutType::Any, "std::ops::Shr"),
(*sym::sub, 2, SelfKind::Value, OutType::Any, "std::ops::Sub"),
];
}
#[rustfmt::skip]
const PATTERN_METHODS: [(&str, usize); 17] = [
("contains", 1),
("starts_with", 1),
("ends_with", 1),
("find", 1),
("rfind", 1),
("split", 1),
("rsplit", 1),
("split_terminator", 1),
("rsplit_terminator", 1),
("splitn", 2),
("rsplitn", 2),
("matches", 1),
("rmatches", 1),
("match_indices", 1),
("rmatch_indices", 1),
("trim_start_matches", 1),
("trim_end_matches", 1),
lazy_static! {
static ref PATTERN_METHODS: [(Symbol, usize); 17] = [
(*sym::contains, 1),
(*sym::starts_with, 1),
(*sym::ends_with, 1),
(*sym::find, 1),
(*sym::rfind, 1),
(*sym::split, 1),
(*sym::rsplit, 1),
(*sym::split_terminator, 1),
(*sym::rsplit_terminator, 1),
(*sym::splitn, 2),
(*sym::rsplitn, 2),
(*sym::matches, 1),
(*sym::rmatches, 1),
(*sym::match_indices, 1),
(*sym::rmatch_indices, 1),
(*sym::trim_start_matches, 1),
(*sym::trim_end_matches, 1),
];
}
#[derive(Clone, Copy, PartialEq, Debug)]
enum SelfKind {
@ -2474,8 +2482,8 @@ impl SelfKind {
} else {
match self {
SelfKind::Value => false,
SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT),
SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT),
SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &*paths::ASREF_TRAIT),
SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &*paths::ASMUT_TRAIT),
SelfKind::No => true,
}
}
@ -2491,7 +2499,7 @@ impl SelfKind {
}
}
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool {
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[Symbol]) -> bool {
single_segment_ty(ty).map_or(false, |seg| {
generics.params.iter().any(|param| match param.kind {
hir::GenericParamKind::Type { .. } => {
@ -2595,7 +2603,7 @@ impl OutType {
fn is_bool(ty: &hir::Ty) -> bool {
if let hir::TyKind::Path(ref p) = ty.node {
match_qpath(p, &["bool"])
match_qpath(p, &[*sym::bool])
} else {
false
}

View File

@ -16,7 +16,7 @@ pub(super) fn lint<'a, 'tcx>(
unwrap_args: &'tcx [hir::Expr],
) {
// lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &*paths::OPTION) {
if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) {
// Do not lint if the `map` argument uses identifiers in the `map`
// argument that are also used in the `unwrap_or` argument

View File

@ -11,7 +11,7 @@ use if_chain::if_chain;
use super::UNNECESSARY_FILTER_MAP;
pub(super) fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
if !match_trait_method(cx, expr, &paths::ITERATOR) {
if !match_trait_method(cx, expr, &*paths::ITERATOR) {
return;
}
@ -63,7 +63,7 @@ fn check_expression<'a, 'tcx: 'a>(
if_chain! {
if let hir::ExprKind::Path(ref path) = func.node;
then {
if match_qpath(path, &paths::OPTION_SOME) {
if match_qpath(path, &*paths::OPTION_SOME) {
if_chain! {
if let hir::ExprKind::Path(path) = &args[0].node;
if let Res::Local(ref local) = cx.tables.qpath_res(path, args[0].hir_id);
@ -99,7 +99,7 @@ fn check_expression<'a, 'tcx: 'a>(
}
(found_mapping, found_filtering)
},
hir::ExprKind::Path(path) if match_qpath(path, &paths::OPTION_NONE) => (false, true),
hir::ExprKind::Path(path) if match_qpath(path, &*paths::OPTION_NONE) => (false, true),
_ => (true, true),
}
}

View File

@ -1,5 +1,5 @@
use crate::consts::{constant_simple, Constant};
use crate::utils::{paths, span_lint};
use crate::utils::{paths, span_lint, match_def_path};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -63,9 +63,9 @@ fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(MinMax, Cons
if let ExprKind::Call(ref path, ref args) = expr.node {
if let ExprKind::Path(ref qpath) = path.node {
cx.tables.qpath_res(qpath, path.hir_id).opt_def_id().and_then(|def_id| {
if cx.match_def_path(def_id, &paths::CMP_MIN) {
if match_def_path(cx, def_id, &*paths::CMP_MIN) {
fetch_const(cx, args, MinMax::Min)
} else if cx.match_def_path(def_id, &paths::CMP_MAX) {
} else if match_def_path(cx, def_id, &*paths::CMP_MAX) {
fetch_const(cx, args, MinMax::Max)
} else {
None

View File

@ -11,6 +11,7 @@ use syntax::source_map::{ExpnFormat, Span};
use crate::consts::{constant, Constant};
use crate::utils::sugg::Sugg;
use crate::utils::sym;
use crate::utils::{
get_item_name, get_parent_expr, implements_trait, in_constant, in_macro_or_desugar, is_integer_literal,
iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then,
@ -461,7 +462,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
fn check_nan(cx: &LateContext<'_, '_>, path: &Path, expr: &Expr) {
if !in_constant(cx, expr.hir_id) {
if let Some(seg) = path.segments.last() {
if seg.ident.name == "NAN" {
if seg.ident.name == *sym::NAN {
span_lint(
cx,
CMP_NAN,
@ -496,7 +497,7 @@ fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
let (arg_ty, snip) = match expr.node {
ExprKind::MethodCall(.., ref args) if args.len() == 1 => {
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
if match_trait_method(cx, expr, &*paths::TO_STRING) || match_trait_method(cx, expr, &*paths::TO_OWNED) {
(cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
} else {
return;
@ -504,7 +505,7 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
},
ExprKind::Call(ref path, ref v) if v.len() == 1 => {
if let ExprKind::Path(ref path) = path.node {
if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
if match_qpath(path, &[*sym::String, *sym::from_str]) || match_qpath(path, &[*sym::String, *sym::from]) {
(cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, ".."))
} else {
return;

View File

@ -6,6 +6,7 @@
//
use crate::utils::{in_macro_or_desugar, span_lint};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
@ -91,7 +92,7 @@ impl MissingDoc {
let has_doc = attrs
.iter()
.any(|a| a.check_name("doc") && (a.is_value_str() || Self::has_include(a.meta())));
.any(|a| a.check_name(*sym::doc) && (a.is_value_str() || Self::has_include(a.meta())));
if !has_doc {
span_lint(
cx,
@ -109,10 +110,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
let doc_hidden = self.doc_hidden()
|| attrs.iter().any(|attr| {
attr.check_name("doc")
attr.check_name(*sym::doc)
&& match attr.meta_item_list() {
None => false,
Some(l) => attr::list_contains_name(&l[..], "hidden"),
Some(l) => attr::list_contains_name(&l[..], *sym::hidden),
}
});
self.doc_hidden_stack.push(doc_hidden);
@ -132,7 +133,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
hir::ItemKind::Enum(..) => "an enum",
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == "main" {
if it.ident.name == *sym::main {
let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
let def_key = cx.tcx.hir().def_key(def_id);
if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {

View File

@ -1,4 +1,5 @@
use crate::utils::span_lint;
use crate::utils::sym;
use rustc::hir;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -57,7 +58,7 @@ declare_clippy_lint! {
}
fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
let has_inline = attrs.iter().any(|a| a.check_name("inline"));
let has_inline = attrs.iter().any(|a| a.check_name(*sym::inline));
if !has_inline {
span_lint(
cx,

View File

@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Mutex {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
let ty = cx.tables.expr_ty(expr);
if let ty::Adt(_, subst) = ty.sty {
if match_type(cx, ty, &paths::MUTEX) {
if match_type(cx, ty, &*paths::MUTEX) {
let mutex_param = subst.type_at(0);
if let Some(atomic_name) = get_atomic_name(mutex_param) {
let msg = format!(

View File

@ -3,6 +3,7 @@
//! This lint is **warn** by default
use crate::utils::{in_macro_or_desugar, snippet_opt, span_lint_and_then};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::{BindingAnnotation, Expr, ExprKind, HirId, Item, MutImmutable, Pat, PatKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -108,7 +109,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
}
fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if item.attrs.iter().any(|a| a.check_name("automatically_derived")) {
if item.attrs.iter().any(|a| a.check_name(*sym::automatically_derived)) {
debug_assert!(self.derived_item.is_none());
self.derived_item = Some(item.hir_id);
}

View File

@ -1,4 +1,5 @@
use crate::utils::ptr::get_spans;
use crate::utils::sym;
use crate::utils::{
get_trait_def_id, implements_trait, in_macro_or_desugar, is_copy, is_self, match_type, multispan_sugg, paths,
snippet, snippet_opt, span_lint_and_then,
@ -101,12 +102,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
}
// Allow `Borrow` or functions to be taken by value
let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT));
let borrow_trait = need!(get_trait_def_id(cx, &*paths::BORROW_TRAIT));
let whitelisted_traits = [
need!(cx.tcx.lang_items().fn_trait()),
need!(cx.tcx.lang_items().fn_once_trait()),
need!(cx.tcx.lang_items().fn_mut_trait()),
need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)),
need!(get_trait_def_id(cx, &*paths::RANGE_ARGUMENT_TRAIT)),
];
let sized_trait = need!(cx.tcx.lang_items().sized_trait());
@ -214,12 +215,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
let deref_span = spans_need_deref.get(&canonical_id);
if_chain! {
if match_type(cx, ty, &paths::VEC);
if match_type(cx, ty, &*paths::VEC);
if let Some(clone_spans) =
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]);
get_spans(cx, Some(body.id()), idx, &[(*sym::clone, ".to_owned()")]);
if let TyKind::Path(QPath::Resolved(_, ref path)) = input.node;
if let Some(elem_ty) = path.segments.iter()
.find(|seg| seg.ident.name == "Vec")
.find(|seg| seg.ident.name == *sym::Vec)
.and_then(|ps| ps.args.as_ref())
.map(|params| params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
@ -253,9 +254,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
}
}
if match_type(cx, ty, &paths::STRING) {
if match_type(cx, ty, &*paths::STRING) {
if let Some(clone_spans) =
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) {
get_spans(cx, Some(body.id()), idx, &[(*sym::clone, ".to_string()"), (*sym::as_str, "")]) {
db.span_suggestion(
input.span,
"consider changing the type to",
@ -312,7 +313,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
/// Functions marked with these attributes must have the exact signature.
fn requires_exact_signature(attrs: &[Attribute]) -> bool {
attrs.iter().any(|attr| {
["proc_macro", "proc_macro_attribute", "proc_macro_derive"]
[*sym::proc_macro, *sym::proc_macro_attribute, *sym::proc_macro_derive]
.iter()
.any(|&allow| attr.check_name(allow))
})

View File

@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
let ty = cx.tables.expr_ty(left);
let implements_ord = {
if let Some(id) = utils::get_trait_def_id(cx, &paths::ORD) {
if let Some(id) = utils::get_trait_def_id(cx, &*paths::ORD) {
utils::implements_trait(cx, ty, id, &[])
} else {
return;
@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
};
let implements_partial_ord = {
if let Some(id) = utils::get_trait_def_id(cx, &paths::PARTIAL_ORD) {
if let Some(id) = utils::get_trait_def_id(cx, &*paths::PARTIAL_ORD) {
utils::implements_trait(cx, ty, id, &[])
} else {
return;

View File

@ -1,4 +1,5 @@
use crate::utils::paths;
use crate::utils::sym;
use crate::utils::sugg::DiagnosticBuilderExt;
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then};
use if_chain::if_chain;
@ -120,12 +121,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
// impl of `Default`
return;
}
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
if sig.decl.inputs.is_empty() && name == *sym::new && cx.access_levels.is_reachable(id) {
let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id));
let self_ty = cx.tcx.type_of(self_did);
if_chain! {
if same_tys(cx, self_ty, return_ty(cx, id));
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
if let Some(default_trait_id) = get_trait_def_id(cx, &*paths::DEFAULT_TRAIT);
then {
if self.impling_types.is_none() {
let mut impls = NodeSet::default();

View File

@ -1,4 +1,5 @@
use crate::utils::{span_lint, span_lint_and_then};
use crate::utils::sym;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_tool_lint, impl_lint_pass};
use syntax::ast::*;
@ -355,7 +356,7 @@ impl EarlyLintPass for NonExpressiveNames {
}
fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) {
if !attr::contains_name(attrs, "test") {
if !attr::contains_name(attrs, *sym::test) {
let mut visitor = SimilarNamesLocalVisitor {
names: Vec::new(),
cx,

View File

@ -1,4 +1,5 @@
use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -43,10 +44,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
if let MatchSource::IfLetDesugar { .. } = *source; //test if it is an If Let
if let ExprKind::MethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result<T,E>.ok()
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
if method_chain_args(op, &[*sym::ok]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
then {
let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT);
let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &*paths::RESULT);
let some_expr_string = snippet(cx, y[0].span, "");
if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type {
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,

View File

@ -1,4 +1,5 @@
use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty};
use crate::utils::sym;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -31,7 +32,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = e.node {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
if path.ident.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
if path.ident.name == *sym::open && match_type(cx, obj_ty, &*paths::OPEN_OPTIONS) {
let mut options = Vec::new();
get_open_options(cx, &arguments[0], &mut options);
check_open_options(cx, &options, e.span);
@ -61,7 +62,7 @@ fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr, options: &mut Vec
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {
if match_type(cx, obj_ty, &*paths::OPEN_OPTIONS) && arguments.len() >= 2 {
let argument_option = match arguments[1].node {
ExprKind::Lit(ref span) => {
if let Spanned {

View File

@ -1,4 +1,5 @@
use crate::utils::{is_direct_expn_of, is_expn_of, paths, resolve_node, span_lint};
use crate::utils::{is_direct_expn_of, is_expn_of, paths, resolve_node, span_lint, match_def_path};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -52,10 +53,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PanicUnimplemented {
if let ExprKind::Call(ref fun, ref params) = ex.node;
if let ExprKind::Path(ref qpath) = fun.node;
if let Some(fun_def_id) = resolve_node(cx, qpath, fun.hir_id).opt_def_id();
if cx.match_def_path(fun_def_id, &paths::BEGIN_PANIC);
if match_def_path(cx, fun_def_id, &*paths::BEGIN_PANIC);
if params.len() == 2;
then {
if is_expn_of(expr.span, "unimplemented").is_some() {
if is_expn_of(expr.span, *sym::unimplemented).is_some() {
let span = get_outer_span(expr);
span_lint(cx, UNIMPLEMENTED, span,
"`unimplemented` should not be present in production code");
@ -82,7 +83,7 @@ fn get_outer_span(expr: &Expr) -> Span {
fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext<'_, '_>) {
if_chain! {
if let ExprKind::Lit(ref lit) = params[0].node;
if is_direct_expn_of(expr.span, "panic").is_some();
if is_direct_expn_of(expr.span, *sym::panic).is_some();
if let LitKind::Str(ref string, _) = lit.node;
let string = string.as_str().replace("{{", "").replace("}}", "");
if let Some(par) = string.find('{');

View File

@ -1,4 +1,5 @@
use crate::utils::{is_automatically_derived, span_lint_hir};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -39,7 +40,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PartialEqNeImpl {
if trait_ref.path.res.def_id() == eq_trait;
then {
for impl_item in impl_items {
if impl_item.ident.name == "ne" {
if impl_item.ident.name == *sym::ne {
span_lint_hir(
cx,
PARTIALEQ_NE_IMPL,

View File

@ -1,4 +1,5 @@
use crate::utils::{match_type, paths, span_lint_and_sugg, walk_ptrs_ty};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -44,9 +45,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
if path.ident.name == "push";
if path.ident.name == *sym::push;
if args.len() == 2;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF);
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &*paths::PATH_BUF);
if let Some(get_index_arg) = args.get(1);
if let ExprKind::Lit(ref lit) = get_index_arg.node;
if let LitKind::Str(ref path_lit, _) = lit.node;

View File

@ -1,6 +1,7 @@
//! Checks for usage of `&Vec[_]` and `&String`.
use crate::utils::ptr::get_spans;
use crate::utils::sym;
use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty};
use if_chain::if_chain;
use rustc::hir::QPath;
@ -148,7 +149,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: HirId, opt_body_id:
for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
if let ty::Ref(_, ty, MutImmutable) = ty.sty {
if match_type(cx, ty, &paths::VEC) {
if match_type(cx, ty, &*paths::VEC) {
let mut ty_snippet = None;
if_chain! {
if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
@ -163,7 +164,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: HirId, opt_body_id:
}
}
};
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[(*sym::clone, ".to_owned()")]) {
span_lint_and_then(
cx,
PTR_ARG,
@ -192,8 +193,8 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: HirId, opt_body_id:
},
);
}
} else if match_type(cx, ty, &paths::STRING) {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
} else if match_type(cx, ty, &*paths::STRING) {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[(*sym::clone, ".to_string()"), (*sym::as_str, "")]) {
span_lint_and_then(
cx,
PTR_ARG,
@ -214,7 +215,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: HirId, opt_body_id:
},
);
}
} else if match_type(cx, ty, &paths::COW) {
} else if match_type(cx, ty, &*paths::COW) {
if_chain! {
if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.node;
if let TyKind::Path(ref path) = ty.node;
@ -293,7 +294,7 @@ fn is_null_path(expr: &Expr) -> bool {
if let ExprKind::Call(ref pathexp, ref args) = expr.node {
if args.is_empty() {
if let ExprKind::Path(ref path) = pathexp.node {
return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT);
return match_qpath(path, &*paths::PTR_NULL) || match_qpath(path, &*paths::PTR_NULL_MUT);
}
}
}

View File

@ -1,4 +1,5 @@
use crate::utils;
use crate::utils::sym;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
@ -92,10 +93,10 @@ fn expr_as_ptr_offset_call<'a, 'tcx>(
) -> Option<(&'tcx Expr, &'tcx Expr, Method)> {
if let ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node {
if is_expr_ty_raw_ptr(cx, &args[0]) {
if path_segment.ident.name == "offset" {
if path_segment.ident.name == *sym::offset {
return Some((&args[0], &args[1], Method::Offset));
}
if path_segment.ident.name == "wrapping_offset" {
if path_segment.ident.name == *sym::wrapping_offset {
return Some((&args[0], &args[1], Method::WrappingOffset));
}
}

View File

@ -7,8 +7,9 @@ use rustc_errors::Applicability;
use syntax::ptr::P;
use crate::utils::paths::*;
use crate::utils::sym;
use crate::utils::sugg::Sugg;
use crate::utils::{higher, match_type, span_lint_and_then, SpanlessEq};
use crate::utils::{higher, match_type, span_lint_and_then, SpanlessEq, match_def_path};
declare_clippy_lint! {
/// **What it does:** Checks for expressions that could be replaced by the question mark operator.
@ -50,7 +51,7 @@ impl QuestionMark {
if_chain! {
if let Some((if_expr, body, else_)) = higher::if_block(&expr);
if let ExprKind::MethodCall(segment, _, args) = &if_expr.node;
if segment.ident.name == "is_none";
if segment.ident.name == *sym::is_none;
if Self::expression_returns_none(cx, body);
if let Some(subject) = args.get(0);
if Self::is_option(cx, subject);
@ -103,7 +104,7 @@ impl QuestionMark {
fn is_option(cx: &LateContext<'_, '_>, expression: &Expr) -> bool {
let expr_ty = cx.tables.expr_ty(expression);
match_type(cx, expr_ty, &OPTION)
match_type(cx, expr_ty, &*OPTION)
}
fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr) -> bool {
@ -120,7 +121,7 @@ impl QuestionMark {
if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
cx.tables.qpath_res(qp, expression.hir_id)
{
return cx.match_def_path(def_id, &OPTION_NONE);
return match_def_path(cx, def_id, &*OPTION_NONE);
}
false

View File

@ -7,6 +7,7 @@ use syntax::ast::RangeLimits;
use syntax::source_map::Spanned;
use crate::utils::sugg::Sugg;
use crate::utils::sym;
use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then};
@ -115,13 +116,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
if_chain! {
// `.iter()` call
if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
if iter_path.ident.name == "iter";
if iter_path.ident.name == *sym::iter;
// range expression in `.zip()` call: `0..x.len()`
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
if is_integer_literal(start, 0);
// `.len()` call
if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.node;
if len_path.ident.name == "len" && len_args.len() == 1;
if len_path.ident.name == *sym::len && len_args.len() == 1;
// `.iter()` and `.len()` called on same `Path`
if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].node;
if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].node;
@ -212,7 +213,7 @@ fn has_step_by(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
// can't be called on a borrowed range.
let ty = cx.tables.expr_ty_adjusted(expr);
get_trait_def_id(cx, &paths::ITERATOR).map_or(false, |iterator_trait| implements_trait(cx, ty, iterator_trait, &[]))
get_trait_def_id(cx, &*paths::ITERATOR).map_or(false, |iterator_trait| implements_trait(cx, ty, iterator_trait, &[]))
}
fn y_plus_one(expr: &Expr) -> Option<&Expr> {

View File

@ -1,6 +1,6 @@
use crate::utils::{
has_drop, in_macro_or_desugar, is_copy, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then,
walk_ptrs_ty_depth,
walk_ptrs_ty_depth, match_def_path,
};
use if_chain::if_chain;
use matches::matches;
@ -94,13 +94,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));
let from_borrow = cx.match_def_path(fn_def_id, &paths::CLONE_TRAIT_METHOD)
|| cx.match_def_path(fn_def_id, &paths::TO_OWNED_METHOD)
|| (cx.match_def_path(fn_def_id, &paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &paths::STRING));
let from_borrow = match_def_path(cx, fn_def_id, &*paths::CLONE_TRAIT_METHOD)
|| match_def_path(cx, fn_def_id, &*paths::TO_OWNED_METHOD)
|| (match_def_path(cx, fn_def_id, &*paths::TO_STRING_METHOD) && match_type(cx, arg_ty, &*paths::STRING));
let from_deref = !from_borrow
&& (cx.match_def_path(fn_def_id, &paths::PATH_TO_PATH_BUF)
|| cx.match_def_path(fn_def_id, &paths::OS_STR_TO_OS_STRING));
&& (match_def_path(cx, fn_def_id, &*paths::PATH_TO_PATH_BUF)
|| match_def_path(cx, fn_def_id, &*paths::OS_STR_TO_OS_STRING));
if !from_borrow && !from_deref {
continue;
@ -133,9 +133,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) =
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
if *res == mir::Place::Base(mir::PlaceBase::Local(cloned));
if cx.match_def_path(pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
if match_def_path(cx, pred_fn_def_id, &*paths::DEREF_TRAIT_METHOD);
if match_type(cx, pred_arg_ty, &*paths::PATH_BUF)
|| match_type(cx, pred_arg_ty, &*paths::OS_STRING);
then {
pred_arg
} else {

View File

@ -5,6 +5,7 @@ use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::LitKind;
use syntax::ptr::P;
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Lint for redundant pattern matching over `Result` or
@ -61,11 +62,11 @@ fn find_sugg_for_if_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr,
let good_method = match arms[0].pats[0].node {
PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => {
if let PatKind::Wild = patterns[0].node {
if match_qpath(path, &paths::RESULT_OK) {
if match_qpath(path, &*paths::RESULT_OK) {
"is_ok()"
} else if match_qpath(path, &paths::RESULT_ERR) {
} else if match_qpath(path, &*paths::RESULT_ERR) {
"is_err()"
} else if match_qpath(path, &paths::OPTION_SOME) {
} else if match_qpath(path, &*paths::OPTION_SOME) {
"is_some()"
} else {
return;
@ -75,7 +76,7 @@ fn find_sugg_for_if_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr,
}
},
PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()",
PatKind::Path(ref path) if match_qpath(path, &*paths::OPTION_NONE) => "is_none()",
_ => return,
};
@ -114,8 +115,8 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, o
arms,
path_left,
path_right,
&paths::RESULT_OK,
&paths::RESULT_ERR,
&*paths::RESULT_OK,
&*paths::RESULT_ERR,
"is_ok()",
"is_err()",
)
@ -132,8 +133,8 @@ fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, o
arms,
path_left,
path_right,
&paths::OPTION_SOME,
&paths::OPTION_NONE,
&*paths::OPTION_SOME,
&*paths::OPTION_NONE,
"is_some()",
"is_none()",
)
@ -170,8 +171,8 @@ fn find_good_method_for_match<'a>(
arms: &HirVec<Arm>,
path_left: &QPath,
path_right: &QPath,
expected_left: &[&str],
expected_right: &[&str],
expected_left: &[Symbol],
expected_right: &[Symbol],
should_be_left: &'a str,
should_be_right: &'a str,
) -> Option<&'a str> {

View File

@ -1,5 +1,6 @@
use crate::consts::{constant, Constant};
use crate::utils::{is_expn_of, match_type, paths, span_help_and_lint, span_lint};
use crate::utils::{is_expn_of, match_type, paths, span_help_and_lint, span_lint, match_def_path};
use crate::utils::sym;
use if_chain::if_chain;
use regex_syntax;
use rustc::hir::*;
@ -83,8 +84,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex {
if_chain! {
if self.last.is_none();
if let Some(ref expr) = block.expr;
if match_type(cx, cx.tables.expr_ty(expr), &paths::REGEX);
if let Some(span) = is_expn_of(expr.span, "regex");
if match_type(cx, cx.tables.expr_ty(expr), &*paths::REGEX);
if let Some(span) = is_expn_of(expr.span, *sym::regex);
then {
if !self.spans.contains(&span) {
span_lint(cx,
@ -112,15 +113,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex {
if args.len() == 1;
if let Some(def_id) = cx.tables.qpath_res(qpath, fun.hir_id).opt_def_id();
then {
if cx.match_def_path(def_id, &paths::REGEX_NEW) ||
cx.match_def_path(def_id, &paths::REGEX_BUILDER_NEW) {
if match_def_path(cx, def_id, &*paths::REGEX_NEW) ||
match_def_path(cx, def_id, &*paths::REGEX_BUILDER_NEW) {
check_regex(cx, &args[0], true);
} else if cx.match_def_path(def_id, &paths::REGEX_BYTES_NEW) ||
cx.match_def_path(def_id, &paths::REGEX_BYTES_BUILDER_NEW) {
} else if match_def_path(cx, def_id, &*paths::REGEX_BYTES_NEW) ||
match_def_path(cx, def_id, &*paths::REGEX_BYTES_BUILDER_NEW) {
check_regex(cx, &args[0], false);
} else if cx.match_def_path(def_id, &paths::REGEX_SET_NEW) {
} else if match_def_path(cx, def_id, &*paths::REGEX_SET_NEW) {
check_set(cx, &args[0], true);
} else if cx.match_def_path(def_id, &paths::REGEX_BYTES_SET_NEW) {
} else if match_def_path(cx, def_id, &*paths::REGEX_BYTES_SET_NEW) {
check_set(cx, &args[0], false);
}
}

View File

@ -1,10 +1,13 @@
use crate::utils::span_lint_and_sugg;
use crate::utils::{span_lint_and_sugg, match_def_path};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
declare_clippy_lint! {
/// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and
@ -37,8 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
if let hir::ExprKind::Path(ref qp) = expr.node;
if let Res::Def(DefKind::Const, def_id) = cx.tables.qpath_res(qp, expr.hir_id);
then {
for &(const_path, repl_snip) in REPLACEMENTS {
if cx.match_def_path(def_id, const_path) {
for (const_path, repl_snip) in REPLACEMENTS.iter() {
if match_def_path(cx, def_id, const_path) {
span_lint_and_sugg(
cx,
REPLACE_CONSTS,
@ -56,33 +59,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
}
}
const REPLACEMENTS: &[(&[&str], &str)] = &[
lazy_static! {
static ref REPLACEMENTS: [([Symbol; 3], &'static str); 25] = [
// Once
(&["core", "sync", "ONCE_INIT"], "Once::new()"),
([*sym::core, *sym::sync, *sym::ONCE_INIT], "Once::new()"),
// Min
(&["core", "isize", "MIN"], "isize::min_value()"),
(&["core", "i8", "MIN"], "i8::min_value()"),
(&["core", "i16", "MIN"], "i16::min_value()"),
(&["core", "i32", "MIN"], "i32::min_value()"),
(&["core", "i64", "MIN"], "i64::min_value()"),
(&["core", "i128", "MIN"], "i128::min_value()"),
(&["core", "usize", "MIN"], "usize::min_value()"),
(&["core", "u8", "MIN"], "u8::min_value()"),
(&["core", "u16", "MIN"], "u16::min_value()"),
(&["core", "u32", "MIN"], "u32::min_value()"),
(&["core", "u64", "MIN"], "u64::min_value()"),
(&["core", "u128", "MIN"], "u128::min_value()"),
([*sym::core, *sym::isize, *sym::MIN], "isize::min_value()"),
([*sym::core, *sym::i8, *sym::MIN], "i8::min_value()"),
([*sym::core, *sym::i16, *sym::MIN], "i16::min_value()"),
([*sym::core, *sym::i32, *sym::MIN], "i32::min_value()"),
([*sym::core, *sym::i64, *sym::MIN], "i64::min_value()"),
([*sym::core, *sym::i128, *sym::MIN], "i128::min_value()"),
([*sym::core, *sym::usize, *sym::MIN], "usize::min_value()"),
([*sym::core, *sym::u8, *sym::MIN], "u8::min_value()"),
([*sym::core, *sym::u16, *sym::MIN], "u16::min_value()"),
([*sym::core, *sym::u32, *sym::MIN], "u32::min_value()"),
([*sym::core, *sym::u64, *sym::MIN], "u64::min_value()"),
([*sym::core, *sym::u128, *sym::MIN], "u128::min_value()"),
// Max
(&["core", "isize", "MAX"], "isize::max_value()"),
(&["core", "i8", "MAX"], "i8::max_value()"),
(&["core", "i16", "MAX"], "i16::max_value()"),
(&["core", "i32", "MAX"], "i32::max_value()"),
(&["core", "i64", "MAX"], "i64::max_value()"),
(&["core", "i128", "MAX"], "i128::max_value()"),
(&["core", "usize", "MAX"], "usize::max_value()"),
(&["core", "u8", "MAX"], "u8::max_value()"),
(&["core", "u16", "MAX"], "u16::max_value()"),
(&["core", "u32", "MAX"], "u32::max_value()"),
(&["core", "u64", "MAX"], "u64::max_value()"),
(&["core", "u128", "MAX"], "u128::max_value()"),
([*sym::core, *sym::isize, *sym::MAX], "isize::max_value()"),
([*sym::core, *sym::i8, *sym::MAX], "i8::max_value()"),
([*sym::core, *sym::i16, *sym::MAX], "i16::max_value()"),
([*sym::core, *sym::i32, *sym::MAX], "i32::max_value()"),
([*sym::core, *sym::i64, *sym::MAX], "i64::max_value()"),
([*sym::core, *sym::i128, *sym::MAX], "i128::max_value()"),
([*sym::core, *sym::usize, *sym::MAX], "usize::max_value()"),
([*sym::core, *sym::u8, *sym::MAX], "u8::max_value()"),
([*sym::core, *sym::u16, *sym::MAX], "u16::max_value()"),
([*sym::core, *sym::u32, *sym::MAX], "u32::max_value()"),
([*sym::core, *sym::u64, *sym::MAX], "u64::max_value()"),
([*sym::core, *sym::u128, *sym::MAX], "u128::max_value()"),
];
}

View File

@ -8,6 +8,7 @@ use syntax::visit::FnKind;
use syntax_pos::BytePos;
use crate::utils::{in_macro_or_desugar, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint};
use crate::utils::sym;
declare_clippy_lint! {
/// **What it does:** Checks for return statements at the end of a block.
@ -161,7 +162,7 @@ impl Return {
if let Some(ref initexpr) = local.init;
if let ast::PatKind::Ident(_, ident, _) = local.pat.node;
if let ast::ExprKind::Path(_, ref path) = retexpr.node;
if match_path_ast(path, &[&ident.as_str()]);
if match_path_ast(path, &[ident.name]);
if !in_external_macro(cx.sess(), initexpr.span);
then {
span_note_and_lint(cx,
@ -252,7 +253,7 @@ impl EarlyLintPass for Return {
}
fn attr_is_cfg(attr: &ast::Attribute) -> bool {
attr.meta_item_list().is_some() && attr.check_name("cfg")
attr.meta_item_list().is_some() && attr.check_name(*sym::cfg)
}
// get the def site

View File

@ -24,7 +24,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SerdeAPI {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref items) = item.node {
let did = trait_ref.path.res.def_id();
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
if let Some(visit_did) = get_trait_def_id(cx, &*paths::SERDE_DE_VISITOR) {
if did == visit_did {
let mut seen_str = None;
let mut seen_string = None;

View File

@ -1,5 +1,6 @@
use crate::utils::sugg::Sugg;
use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor};
use rustc::hir::*;
@ -109,7 +110,7 @@ impl SlowVectorInit {
if_chain! {
if let ExprKind::Call(ref func, ref args) = expr.node;
if let ExprKind::Path(ref path) = func.node;
if match_qpath(path, &["Vec", "with_capacity"]);
if match_qpath(path, &[*sym::Vec, *sym::with_capacity]);
if args.len() == 1;
then {
@ -200,8 +201,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
if self.initialization_found;
if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
if let ExprKind::Path(ref qpath_subj) = args[0].node;
if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]);
if path.ident.name == "extend";
if match_qpath(&qpath_subj, &[self.vec_alloc.variable_name]);
if path.ident.name == *sym::extend;
if let Some(ref extend_arg) = args.get(1);
if self.is_repeat_take(extend_arg);
@ -217,8 +218,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
if self.initialization_found;
if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
if let ExprKind::Path(ref qpath_subj) = args[0].node;
if match_qpath(&qpath_subj, &[&self.vec_alloc.variable_name.to_string()]);
if path.ident.name == "resize";
if match_qpath(&qpath_subj, &[self.vec_alloc.variable_name]);
if path.ident.name == *sym::resize;
if let (Some(ref len_arg), Some(fill_arg)) = (args.get(1), args.get(2));
// Check that is filled with 0
@ -238,7 +239,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
fn is_repeat_take(&self, expr: &Expr) -> bool {
if_chain! {
if let ExprKind::MethodCall(ref take_path, _, ref take_args) = expr.node;
if take_path.ident.name == "take";
if take_path.ident.name == *sym::take;
// Check that take is applied to `repeat(0)`
if let Some(ref repeat_expr) = take_args.get(0);
@ -261,7 +262,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
if_chain! {
if let ExprKind::Call(ref fn_expr, ref repeat_args) = expr.node;
if let ExprKind::Path(ref qpath_repeat) = fn_expr.node;
if match_qpath(&qpath_repeat, &["repeat"]);
if match_qpath(&qpath_repeat, &[*sym::repeat]);
if let Some(ref repeat_arg) = repeat_args.get(0);
if let ExprKind::Lit(ref lit) = repeat_arg.node;
if let LitKind::Int(0, _) = lit.node;

View File

@ -5,6 +5,7 @@ use rustc_errors::Applicability;
use syntax::source_map::Spanned;
use crate::utils::SpanlessEq;
use crate::utils::sym;
use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty};
declare_clippy_lint! {
@ -119,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd {
}
fn is_string(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(e)), &paths::STRING)
match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(e)), &*paths::STRING)
}
fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool {
@ -146,7 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
use syntax::ast::{LitKind, StrStyle};
if let ExprKind::MethodCall(ref path, _, ref args) = e.node {
if path.ident.name == "as_bytes" {
if path.ident.name == *sym::as_bytes {
if let ExprKind::Lit(ref lit) = args[0].node {
if let LitKind::Str(ref lit_content, style) = lit.node {
let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#);

View File

@ -1,9 +1,11 @@
use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g.
@ -89,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
cx,
expr,
binop.node,
&["Add", "Sub", "Mul", "Div"],
&[*sym::Add, *sym::Sub, *sym::Mul, *sym::Div],
&[
hir::BinOpKind::Add,
hir::BinOpKind::Sub,
@ -110,16 +112,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
expr,
binop.node,
&[
"AddAssign",
"SubAssign",
"MulAssign",
"DivAssign",
"BitAndAssign",
"BitOrAssign",
"BitXorAssign",
"RemAssign",
"ShlAssign",
"ShrAssign",
*sym::AddAssign,
*sym::SubAssign,
*sym::MulAssign,
*sym::DivAssign,
*sym::BitAndAssign,
*sym::BitOrAssign,
*sym::BitXorAssign,
*sym::RemAssign,
*sym::ShlAssign,
*sym::ShrAssign,
],
&[
hir::BinOpKind::Add,
@ -145,17 +147,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
}
}
fn check_binop<'a>(
fn check_binop(
cx: &LateContext<'_, '_>,
expr: &hir::Expr,
binop: hir::BinOpKind,
traits: &[&'a str],
traits: &[Symbol],
expected_ops: &[hir::BinOpKind],
) -> Option<&'a str> {
) -> Option<Symbol> {
let mut trait_ids = vec![];
let [krate, module] = crate::utils::paths::OPS_MODULE;
let [krate, module] = *crate::utils::paths::OPS_MODULE;
for t in traits {
for &t in traits {
let path = [krate, module, t];
if let Some(trait_id) = get_trait_def_id(cx, &path) {
trait_ids.push(trait_id);

View File

@ -96,8 +96,8 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
if matches!(ty.sty, ty::Slice(_)) ||
matches!(ty.sty, ty::Array(_, _)) ||
match_type(cx, ty, &paths::VEC) ||
match_type(cx, ty, &paths::VEC_DEQUE) {
match_type(cx, ty, &*paths::VEC) ||
match_type(cx, ty, &*paths::VEC_DEQUE) {
return Some((lhs1, idx1, idx2));
}
}

View File

@ -1,4 +1,4 @@
use crate::utils::{last_path_segment, paths, snippet, span_lint, span_lint_and_then, sugg};
use crate::utils::{last_path_segment, paths, snippet, span_lint, span_lint_and_then, sugg, match_def_path};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
@ -221,7 +221,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
if let ExprKind::Call(ref path_expr, ref args) = e.node {
if let ExprKind::Path(ref qpath) = path_expr.node {
if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
if cx.match_def_path(def_id, &paths::TRANSMUTE) {
if match_def_path(cx, def_id, &*paths::TRANSMUTE) {
let from_ty = cx.tables.expr_ty(&args[0]);
let to_ty = cx.tables.expr_ty(e);

View File

@ -1,5 +1,5 @@
use crate::consts::{constant_context, Constant};
use crate::utils::{match_qpath, span_lint};
use crate::utils::{paths, match_qpath, span_lint};
use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
@ -37,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TransmutingNull {
if_chain! {
if let ExprKind::Call(ref func, ref args) = expr.node;
if let ExprKind::Path(ref path) = func.node;
if match_qpath(path, &["std", "mem", "transmute"]);
if match_qpath(path, &*paths::STD_MEM_TRANSMUTE);
if args.len() == 1;
then {
@ -79,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TransmutingNull {
if_chain! {
if let ExprKind::Call(ref func1, ref args1) = args[0].node;
if let ExprKind::Path(ref path1) = func1.node;
if match_qpath(path1, &["std", "ptr", "null"]);
if match_qpath(path1, &*paths::STD_PTR_NULL);
if args1.len() == 0;
then {
span_lint(

View File

@ -1,6 +1,7 @@
use std::cmp;
use crate::utils::{in_macro_or_desugar, is_copy, is_self_ty, snippet, span_lint_and_sugg};
use crate::utils::sym;
use if_chain::if_chain;
use matches::matches;
use rustc::hir;
@ -168,7 +169,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
return;
}
for a in attrs {
if a.meta_item_list().is_some() && a.check_name("proc_macro_derive") {
if a.meta_item_list().is_some() && a.check_name(*sym::proc_macro_derive) {
return;
}
}

View File

@ -18,14 +18,16 @@ use rustc_typeck::hir_ty_to_ty;
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::errors::DiagnosticBuilder;
use syntax::source_map::Span;
use syntax::symbol::Symbol;
use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::{
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro_or_desugar, int_bits, last_path_segment,
match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint,
span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
span_lint, span_lint_and_sugg, span_lint_and_then, unsext, match_def_path,
};
use crate::utils::sym;
declare_clippy_lint! {
/// **What it does:** Checks for use of `Box<Vec<_>>` anywhere in the code.
@ -206,7 +208,7 @@ fn check_fn_decl(cx: &LateContext<'_, '_>, decl: &FnDecl) {
}
/// Checks if `qpath` has last segment with type parameter matching `path`
fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str]) -> bool {
fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[Symbol]) -> bool {
let last = last_path_segment(qpath);
if_chain! {
if let Some(ref params) = last.args;
@ -217,7 +219,7 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath, path: &[&str])
});
if let TyKind::Path(ref qpath) = ty.node;
if let Some(did) = cx.tables.qpath_res(qpath, ty.hir_id).opt_def_id();
if cx.match_def_path(did, path);
if match_def_path(cx, did, path);
then {
return true;
}
@ -241,7 +243,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
let res = cx.tables.qpath_res(qpath, hir_id);
if let Some(def_id) = res.opt_def_id() {
if Some(def_id) == cx.tcx.lang_items().owned_box() {
if match_type_parameter(cx, qpath, &paths::VEC) {
if match_type_parameter(cx, qpath, &*paths::VEC) {
span_help_and_lint(
cx,
BOX_VEC,
@ -251,7 +253,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
);
return; // don't recurse into the type
}
} else if cx.match_def_path(def_id, &paths::VEC) {
} else if match_def_path(cx, def_id, &*paths::VEC) {
if_chain! {
// Get the _ part of Vec<_>
if let Some(ref last) = last_path_segment(qpath).args;
@ -286,8 +288,8 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
}
}
}
} else if cx.match_def_path(def_id, &paths::OPTION) {
if match_type_parameter(cx, qpath, &paths::OPTION) {
} else if match_def_path(cx, def_id, &*paths::OPTION) {
if match_type_parameter(cx, qpath, &*paths::OPTION) {
span_lint(
cx,
OPTION_OPTION,
@ -297,7 +299,7 @@ fn check_ty(cx: &LateContext<'_, '_>, hir_ty: &hir::Ty, is_local: bool) {
);
return; // don't recurse into the type
}
} else if cx.match_def_path(def_id, &paths::LINKED_LIST) {
} else if match_def_path(cx, def_id, &*paths::LINKED_LIST) {
span_help_and_lint(
cx,
LINKEDLIST,
@ -426,7 +428,7 @@ fn is_any_trait(t: &hir::Ty) -> bool {
if traits.len() >= 1;
// Only Send/Sync can be used as additional traits, so it is enough to
// check only the first trait.
if match_path(&traits[0].trait_ref.path, &paths::ANY_TRAIT);
if match_path(&traits[0].trait_ref.path, &*paths::ANY_TRAIT);
then {
return true;
}
@ -2087,14 +2089,14 @@ impl<'tcx> ImplicitHasherType<'tcx> {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
if match_path(path, &paths::HASHMAP) && params_len == 2 {
if match_path(path, &*paths::HASHMAP) && params_len == 2 {
Some(ImplicitHasherType::HashMap(
hir_ty.span,
ty,
snippet(cx, params[0].span, "K"),
snippet(cx, params[1].span, "V"),
))
} else if match_path(path, &paths::HASHSET) && params_len == 1 {
} else if match_path(path, &*paths::HASHSET) && params_len == 1 {
Some(ImplicitHasherType::HashSet(
hir_ty.span,
ty,
@ -2197,11 +2199,11 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'
return;
}
if match_path(ty_path, &paths::HASHMAP) {
if method.ident.name == "new" {
if match_path(ty_path, &*paths::HASHMAP) {
if method.ident.name == *sym::new {
self.suggestions
.insert(e.span, "HashMap::default()".to_string());
} else if method.ident.name == "with_capacity" {
} else if method.ident.name == *sym::with_capacity {
self.suggestions.insert(
e.span,
format!(
@ -2210,11 +2212,11 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'
),
);
}
} else if match_path(ty_path, &paths::HASHSET) {
if method.ident.name == "new" {
} else if match_path(ty_path, &*paths::HASHSET) {
if method.ident.name == *sym::new {
self.suggestions
.insert(e.span, "HashSet::default()".to_string());
} else if method.ident.name == "with_capacity" {
} else if method.ident.name == *sym::with_capacity {
self.suggestions.insert(
e.span,
format!(

View File

@ -43,7 +43,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
hir::ExprKind::Match(ref res, _, _) if is_try(expr).is_some() => {
if let hir::ExprKind::Call(ref func, ref args) = res.node {
if let hir::ExprKind::Path(ref path) = func.node {
if match_qpath(path, &paths::TRY_INTO_RESULT) && args.len() == 1 {
if match_qpath(path, &*paths::TRY_INTO_RESULT) && args.len() == 1 {
check_method_call(cx, &args[0], expr);
}
}
@ -67,14 +67,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr, expr: &hir::Expr) {
if let hir::ExprKind::MethodCall(ref path, _, _) = call.node {
let symbol = &*path.ident.as_str();
if match_trait_method(cx, call, &paths::IO_READ) && symbol == "read" {
if match_trait_method(cx, call, &*paths::IO_READ) && symbol == "read" {
span_lint(
cx,
UNUSED_IO_AMOUNT,
expr.span,
"handle read amount returned or use `Read::read_exact` instead",
);
} else if match_trait_method(cx, call, &paths::IO_WRITE) && symbol == "write" {
} else if match_trait_method(cx, call, &*paths::IO_WRITE) && symbol == "write" {
span_lint(
cx,
UNUSED_IO_AMOUNT,

View File

@ -5,6 +5,7 @@ use rustc::{declare_lint_pass, declare_tool_lint};
use crate::utils::{
higher::if_block, in_macro_or_desugar, match_type, paths, span_lint_and_then, usage::is_potentially_mutated,
};
use crate::utils::sym;
use rustc::hir::intravisit::*;
use rustc::hir::*;
use syntax::source_map::Span;
@ -95,7 +96,7 @@ fn collect_unwrap_info<'a, 'tcx: 'a>(
if let ExprKind::MethodCall(method_name, _, args) = &expr.node;
if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].node;
let ty = cx.tables.expr_ty(&args[0]);
if match_type(cx, ty, &paths::OPTION) || match_type(cx, ty, &paths::RESULT);
if match_type(cx, ty, &*paths::OPTION) || match_type(cx, ty, &*paths::RESULT);
let name = method_name.ident.as_str();
if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name);
then {
@ -143,8 +144,8 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
if_chain! {
if let ExprKind::MethodCall(ref method_name, _, ref args) = expr.node;
if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].node;
if ["unwrap", "unwrap_err"].contains(&&*method_name.ident.as_str());
let call_to_unwrap = method_name.ident.name == "unwrap";
if [*sym::unwrap, *sym::unwrap_err].contains(&method_name.ident.name);
let call_to_unwrap = method_name.ident.name == *sym::unwrap;
if let Some(unwrappable) = self.unwrappables.iter()
.find(|u| u.ident.res == path.res);
then {

View File

@ -3,6 +3,7 @@
#![deny(clippy::missing_docs_in_private_items)]
use lazy_static::lazy_static;
use crate::utils::sym;
use std::default::Default;
use std::io::Read;
use std::sync::Mutex;
@ -13,7 +14,7 @@ use toml;
/// Gets the configuration file from arguments.
pub fn file_from_args(args: &[ast::NestedMetaItem]) -> Result<Option<path::PathBuf>, (&'static str, source_map::Span)> {
for arg in args.iter().filter_map(syntax::ast::NestedMetaItem::meta_item) {
if arg.check_name("conf_file") {
if arg.check_name(*sym::conf_file) {
return match arg.node {
ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => {
Err(("`conf_file` must be a named value", arg.span))

View File

@ -3,11 +3,13 @@
#![deny(clippy::missing_docs_in_private_items)]
use crate::utils::{is_expn_of, match_qpath, paths, resolve_node};
use crate::utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::lint::LateContext;
use rustc::{hir, ty};
use syntax::ast;
use syntax::symbol::Symbol;
/// Converts a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
@ -48,7 +50,7 @@ pub struct Range<'a> {
pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option<Range<'b>> {
/// Finds the field named `name` in the field. Always return `Some` for
/// convenience.
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
fn get_field<'a>(name: Symbol, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
let expr = &fields.iter().find(|field| field.ident.name == name)?.expr;
Some(expr)
@ -88,7 +90,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O
match expr.node {
hir::ExprKind::Path(ref path) => {
if match_qpath(path, &paths::RANGE_FULL_STD) || match_qpath(path, &paths::RANGE_FULL) {
if match_qpath(path, &*paths::RANGE_FULL_STD) || match_qpath(path, &*paths::RANGE_FULL) {
Some(Range {
start: None,
end: None,
@ -100,7 +102,7 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O
},
hir::ExprKind::Call(ref path, ref args) => {
if let hir::ExprKind::Path(ref path) = path.node {
if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW)
if match_qpath(path, &*paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &*paths::RANGE_INCLUSIVE_NEW)
{
Some(Range {
start: Some(&args[0]),
@ -115,29 +117,29 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O
}
},
hir::ExprKind::Struct(ref path, ref fields, None) => {
if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) {
if match_qpath(path, &*paths::RANGE_FROM_STD) || match_qpath(path, &*paths::RANGE_FROM) {
Some(Range {
start: Some(get_field("start", fields)?),
start: Some(get_field(*sym::start, fields)?),
end: None,
limits: ast::RangeLimits::HalfOpen,
})
} else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) {
} else if match_qpath(path, &*paths::RANGE_STD) || match_qpath(path, &*paths::RANGE) {
Some(Range {
start: Some(get_field("start", fields)?),
end: Some(get_field("end", fields)?),
start: Some(get_field(*sym::start, fields)?),
end: Some(get_field(*sym::end, fields)?),
limits: ast::RangeLimits::HalfOpen,
})
} else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE)
} else if match_qpath(path, &*paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &*paths::RANGE_TO_INCLUSIVE)
{
Some(Range {
start: None,
end: Some(get_field("end", fields)?),
end: Some(get_field(*sym::end, fields)?),
limits: ast::RangeLimits::Closed,
})
} else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) {
} else if match_qpath(path, &*paths::RANGE_TO_STD) || match_qpath(path, &*paths::RANGE_TO) {
Some(Range {
start: None,
end: Some(get_field("end", fields)?),
end: Some(get_field(*sym::end, fields)?),
limits: ast::RangeLimits::HalfOpen,
})
} else {
@ -234,14 +236,14 @@ pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr) -> Option<Ve
if_chain! {
if let hir::ExprKind::Call(ref fun, ref args) = expr.node;
if let hir::ExprKind::Path(ref path) = fun.node;
if is_expn_of(fun.span, "vec").is_some();
if is_expn_of(fun.span, *sym::vec).is_some();
if let Some(fun_def_id) = resolve_node(cx, path, fun.hir_id).opt_def_id();
then {
return if cx.match_def_path(fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
return if match_def_path(cx, fun_def_id, &*paths::VEC_FROM_ELEM) && args.len() == 2 {
// `vec![elem; size]` case
Some(VecArgs::Repeat(&args[0], &args[1]))
}
else if cx.match_def_path(fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
else if match_def_path(cx, fun_def_id, &*paths::SLICE_INTO_VEC) && args.len() == 1 {
// `vec![a, b, c]` case
if_chain! {
if let hir::ExprKind::Box(ref boxed) = args[0].node;

View File

@ -1,4 +1,5 @@
use crate::utils::{match_type, paths, span_help_and_lint, span_lint, walk_ptrs_ty};
use crate::utils::{match_type, match_def_path, paths, span_help_and_lint, span_lint, walk_ptrs_ty};
use crate::utils::sym;
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
@ -76,12 +77,12 @@ declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
impl EarlyLintPass for ClippyLintsInternal {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) {
if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == "utils") {
if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == *sym::utils) {
if let ItemKind::Mod(ref utils_mod) = utils.node {
if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name == "paths") {
if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name == *sym::paths) {
if let ItemKind::Mod(ref paths_mod) = paths.node {
let mut last_name: Option<LocalInternedString> = None;
for item in &paths_mod.items {
for item in &*paths_mod.items {
let name = item.ident.as_str();
if let Some(ref last_name) = last_name {
if **last_name > *name {
@ -121,7 +122,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
if_chain! {
if let hir::TraitRef{path, ..} = trait_ref;
if let Res::Def(DefKind::Trait, def_id) = path.res;
if cx.match_def_path(def_id, &paths::LINT_PASS);
if match_def_path(cx, def_id, &*paths::LINT_PASS);
then {
let mut collector = LintCollector {
output: &mut self.registered_lints,
@ -179,7 +180,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool {
{
if let TyKind::Path(ref path) = inner.node {
if let Res::Def(DefKind::Struct, def_id) = cx.tables.qpath_res(path, inner.hir_id) {
return cx.match_def_path(def_id, &paths::LINT);
return match_def_path(cx, def_id, &*paths::LINT);
}
}
}
@ -233,8 +234,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
let fn_name = path.ident.as_str().to_string();
if let Some(sugg) = self.map.get(&fn_name);
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
if match_type(cx, ty, &paths::EARLY_CONTEXT)
|| match_type(cx, ty, &paths::LATE_CONTEXT);
if match_type(cx, ty, &*paths::EARLY_CONTEXT)
|| match_type(cx, ty, &*paths::LATE_CONTEXT);
then {
span_help_and_lint(
cx,

View File

@ -12,6 +12,7 @@ pub mod internal_lints;
pub mod paths;
pub mod ptr;
pub mod sugg;
pub mod sym;
pub mod usage;
pub use self::attrs::*;
pub use self::diagnostics::*;
@ -121,19 +122,19 @@ pub fn is_present_in_source<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool
}
/// Checks if type is struct, enum or union type with the given def path.
pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[Symbol]) -> bool {
match ty.sty {
ty::Adt(adt, _) => cx.match_def_path(adt.did, path),
ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
_ => false,
}
}
/// Checks if the method call given in `expr` belongs to the given trait.
pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[&str]) -> bool {
pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr, path: &[Symbol]) -> bool {
let def_id = cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
let trt_id = cx.tcx.trait_of_item(def_id);
if let Some(trt_id) = trt_id {
cx.match_def_path(trt_id, path)
match_def_path(cx, trt_id, path)
} else {
false
}
@ -173,7 +174,7 @@ pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> {
/// ```rust,ignore
/// match_qpath(path, &["std", "rt", "begin_unwind"])
/// ```
pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool {
pub fn match_qpath(path: &QPath, segments: &[Symbol]) -> bool {
match *path {
QPath::Resolved(_, ref path) => match_path(path, segments),
QPath::TypeRelative(ref ty, ref segment) => match ty.node {
@ -195,7 +196,7 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool {
/// # Examples
///
/// ```rust,ignore
/// if match_path(&trait_ref.path, &paths::HASH) {
/// if match_path(&trait_ref.path, &*paths::HASH) {
/// // This is the `std::hash::Hash` trait.
/// }
///
@ -203,7 +204,7 @@ pub fn match_qpath(path: &QPath, segments: &[&str]) -> bool {
/// // This is a `rustc::lint::Lint`.
/// }
/// ```
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
pub fn match_path(path: &Path, segments: &[Symbol]) -> bool {
path.segments
.iter()
.rev()
@ -217,7 +218,7 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool {
/// ```rust,ignore
/// match_qpath(path, &["std", "rt", "begin_unwind"])
/// ```
pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
pub fn match_path_ast(path: &ast::Path, segments: &[Symbol]) -> bool {
path.segments
.iter()
.rev()
@ -226,7 +227,7 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
}
/// Gets the definition associated to a path.
pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<(def::Res)> {
pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[Symbol]) -> Option<(def::Res)> {
let crates = cx.tcx.crates();
let krate = crates.iter().find(|&&krate| cx.tcx.crate_name(krate) == path[0]);
if let Some(krate) = krate {
@ -260,7 +261,7 @@ pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<(def::Res)
}
/// Convenience function to get the `DefId` of a trait by path.
pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<DefId> {
pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[Symbol]) -> Option<DefId> {
let res = match path_to_res(cx, path) {
Some(res) => res,
None => return None,
@ -363,7 +364,7 @@ pub fn method_calls<'a>(expr: &'a Expr, max_depth: usize) -> (Vec<Symbol>, Vec<&
/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec`
/// containing the `Expr`s for
/// `.bar()` and `.baz()`
pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a [Expr]>> {
pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[Symbol]) -> Option<Vec<&'a [Expr]>> {
let mut current = expr;
let mut matched = Vec::with_capacity(methods.len());
for method_name in methods.iter().rev() {
@ -683,7 +684,7 @@ pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
/// Returns the pre-expansion span if is this comes from an expansion of the
/// macro `name`.
/// See also `is_direct_expn_of`.
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
pub fn is_expn_of(mut span: Span, name: Symbol) -> Option<Span> {
loop {
let span_name_span = span
.ctxt()
@ -708,7 +709,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
/// `bar!` by
/// `is_direct_expn_of`.
pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
pub fn is_direct_expn_of(span: Span, name: Symbol) -> Option<Span> {
let span_name_span = span
.ctxt()
.outer()
@ -809,7 +810,7 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool {
/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
/// implementations have.
pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
attr::contains_name(attrs, "automatically_derived")
attr::contains_name(attrs, *sym::automatically_derived)
}
/// Remove blocks around an expression.
@ -995,24 +996,24 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_, '_, '_>, node: HirId)
}
/// Returns true if ty has `iter` or `iter_mut` methods
pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> {
pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
// FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
// exists and has the desired signature. Unfortunately FnCtxt is not exported
// so we can't use its `lookup_method` method.
static INTO_ITER_COLLECTIONS: [&[&str]; 13] = [
&paths::VEC,
&paths::OPTION,
&paths::RESULT,
&paths::BTREESET,
&paths::BTREEMAP,
&paths::VEC_DEQUE,
&paths::LINKED_LIST,
&paths::BINARY_HEAP,
&paths::HASHSET,
&paths::HASHMAP,
&paths::PATH_BUF,
&paths::PATH,
&paths::RECEIVER,
let into_iter_collections: [&[Symbol]; 13] = [
&*paths::VEC,
&*paths::OPTION,
&*paths::RESULT,
&*paths::BTREESET,
&*paths::BTREEMAP,
&*paths::VEC_DEQUE,
&*paths::LINKED_LIST,
&*paths::BINARY_HEAP,
&*paths::HASHSET,
&*paths::HASHMAP,
&*paths::PATH_BUF,
&*paths::PATH,
&*paths::RECEIVER,
];
let ty_to_check = match probably_ref_ty.sty {
@ -1021,15 +1022,15 @@ pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Opt
};
let def_id = match ty_to_check.sty {
ty::Array(..) => return Some("array"),
ty::Slice(..) => return Some("slice"),
ty::Array(..) => return Some(*sym::array),
ty::Slice(..) => return Some(*sym::slice),
ty::Adt(adt, _) => adt.did,
_ => return None,
};
for path in &INTO_ITER_COLLECTIONS {
if cx.match_def_path(def_id, path) {
return Some(path.last().unwrap());
for path in into_iter_collections.iter() {
if match_def_path(cx, def_id, path) {
return Some(*path.last().unwrap());
}
}
None
@ -1115,3 +1116,10 @@ mod test {
assert_eq!(result, vec!["foo", "bar", "baz"]);
}
}
pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[Symbol]) -> bool {
// HACK: fix upstream `match_def_path` to take symbols
let syms: Vec<_> = syms.iter().map(|sym| sym.as_str()).collect();
let syms: Vec<_> = syms.iter().map(|sym| &**sym).collect();
cx.match_def_path(did, &syms)
}

View File

@ -1,111 +1,121 @@
//! This module contains paths to types and functions Clippy needs to know
//! about.
pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"];
pub const ARC: [&str; 3] = ["alloc", "sync", "Arc"];
pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"];
pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"];
pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"];
pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"];
pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"];
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"];
pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"];
pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"];
pub const HASH: [&str; 2] = ["hash", "Hash"];
pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"];
pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"];
pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"];
pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"];
pub const INTO: [&str; 3] = ["core", "convert", "Into"];
pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"];
pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"];
pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"];
pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"];
pub const LINT_PASS: [&str; 3] = ["rustc", "lint", "LintPass"];
pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"];
pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"];
pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"];
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
pub const OPTION: [&str; 3] = ["core", "option", "Option"];
pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"];
pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"];
pub const ORD: [&str; 3] = ["core", "cmp", "Ord"];
pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"];
pub const PATH: [&str; 3] = ["std", "path", "Path"];
pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"];
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
pub const PTR_NULL: [&str; 2] = ["ptr", "null"];
pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"];
pub const RANGE: [&str; 3] = ["core", "ops", "Range"];
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"];
pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"];
pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"];
pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"];
pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"];
pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"];
pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"];
pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"];
pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"];
pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"];
pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"];
pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"];
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
pub const REPEAT: [&str; 3] = ["core", "iter", "repeat"];
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"];
pub const STRING: [&str; 3] = ["alloc", "string", "String"];
pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"];
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"];
pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
#![allow(default_hash_types)] // we just look at symbol names, which is good enough everywhere else
use super::sym::{self, *};
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
lazy_static! {
pub static ref ANY_TRAIT: [Symbol; 3] = [*std, *any, *Any];
pub static ref ARC: [Symbol; 3] = [*alloc, *sync, *Arc];
pub static ref ASMUT_TRAIT: [Symbol; 3] = [*core, *convert, *sym::AsMut];
pub static ref ASREF_TRAIT: [Symbol; 3] = [*core, *convert, *sym::AsRef];
pub static ref BEGIN_PANIC: [Symbol; 3] = [*std, *panicking, *begin_panic];
pub static ref BEGIN_PANIC_FMT: [Symbol; 3] = [*std, *panicking, *begin_panic_fmt];
pub static ref BINARY_HEAP: [Symbol; 4] = [*alloc, *collections, *binary_heap, *BinaryHeap];
pub static ref BORROW_TRAIT: [Symbol; 3] = [*core, *borrow, *Borrow];
pub static ref BTREEMAP: [Symbol; 5] = [*alloc, *collections, *btree, *map, *BTreeMap];
pub static ref BTREEMAP_ENTRY: [Symbol; 5] = [*alloc, *collections, *btree, *map, *Entry];
pub static ref BTREESET: [Symbol; 5] = [*alloc, *collections, *btree, *set, *BTreeSet];
pub static ref CLONE_TRAIT: [Symbol; 3] = [*core, *clone, *sym::Clone];
pub static ref CLONE_TRAIT_METHOD: [Symbol; 4] = [*core, *clone, *sym::Clone, *clone];
pub static ref CMP_MAX: [Symbol; 3] = [*core, *cmp, *max];
pub static ref CMP_MIN: [Symbol; 3] = [*core, *cmp, *min];
pub static ref COW: [Symbol; 3] = [*alloc, *borrow, *Cow];
pub static ref CSTRING_NEW: [Symbol; 5] = [*std, *ffi, *c_str, *CString, *new];
pub static ref DEFAULT_TRAIT: [Symbol; 3] = [*core, *default, *sym::Default];
pub static ref DEFAULT_TRAIT_METHOD: [Symbol; 4] = [*core, *default, *sym::Default, *default];
pub static ref DEREF_TRAIT_METHOD: [Symbol; 5] = [*core, *ops, *deref, *Deref, *deref];
pub static ref DISPLAY_FMT_METHOD: [Symbol; 4] = [*core, *fmt, *Display, *fmt];
pub static ref DOUBLE_ENDED_ITERATOR: [Symbol; 4] = [*core, *iter, *traits, *sym::DoubleEndedIterator];
pub static ref DROP: [Symbol; 3] = [*core, *mem, *drop];
pub static ref DROP_TRAIT: [Symbol; 4] = [*core, *ops, *drop, *sym::Drop];
pub static ref DURATION: [Symbol; 3] = [*core, *time, *Duration];
pub static ref EARLY_CONTEXT: [Symbol; 4] = [*rustc, *lint, *context, *EarlyContext];
pub static ref FMT_ARGUMENTS_NEWV1: [Symbol; 4] = [*core, *fmt, *Arguments, *new_v1];
pub static ref FMT_ARGUMENTS_NEWV1FORMATTED: [Symbol; 4] = [*core, *fmt, *Arguments, *new_v1_formatted];
pub static ref FROM_FROM: [Symbol; 4] = [*core, *convert, *sym::From, *from];
pub static ref FROM_TRAIT: [Symbol; 3] = [*core, *convert, *sym::From];
pub static ref HASH: [Symbol; 2] = [*hash, *Hash];
pub static ref HASHMAP: [Symbol; 5] = [*std, *collections, *hash, *map, *HashMap];
pub static ref HASHMAP_ENTRY: [Symbol; 5] = [*std, *collections, *hash, *map, *Entry];
pub static ref HASHSET: [Symbol; 5] = [*std, *collections, *hash, *set, *HashSet];
pub static ref INDEX: [Symbol; 3] = [*core, *ops, *Index];
pub static ref INDEX_MUT: [Symbol; 3] = [*core, *ops, *IndexMut];
pub static ref INIT: [Symbol; 4] = [*core, *intrinsics, *empty_symbol, *init];
pub static ref INTO: [Symbol; 3] = [*core, *convert, *sym::Into];
pub static ref INTO_ITERATOR: [Symbol; 5] = [*core, *iter, *traits, *collect, *sym::IntoIterator];
pub static ref IO_READ: [Symbol; 3] = [*std, *io, *Read];
pub static ref IO_WRITE: [Symbol; 3] = [*std, *io, *Write];
pub static ref ITERATOR: [Symbol; 5] = [*core, *iter, *traits, *iterator, *sym::Iterator];
pub static ref LATE_CONTEXT: [Symbol; 4] = [*rustc, *lint, *context, *LateContext];
pub static ref LINKED_LIST: [Symbol; 4] = [*alloc, *collections, *linked_list, *LinkedList];
pub static ref LINT: [Symbol; 3] = [*rustc, *lint, *Lint];
pub static ref LINT_PASS: [Symbol; 3] = [*rustc, *lint, *LintPass];
pub static ref MEM_DISCRIMINANT: [Symbol; 3] = [*core, *mem, *discriminant];
pub static ref MEM_FORGET: [Symbol; 3] = [*core, *mem, *forget];
pub static ref MEM_REPLACE: [Symbol; 3] = [*core, *mem, *replace];
pub static ref MEM_UNINIT: [Symbol; 3] = [*core, *mem, *uninitialized];
pub static ref MEM_ZEROED: [Symbol; 3] = [*core, *mem, *zeroed];
pub static ref MUTEX: [Symbol; 4] = [*std, *sync, *mutex, *Mutex];
pub static ref OPEN_OPTIONS: [Symbol; 3] = [*std, *fs, *OpenOptions];
pub static ref OPS_MODULE: [Symbol; 2] = [*core, *ops];
pub static ref OPTION: [Symbol; 3] = [*core, *option, *sym::Option];
pub static ref OPTION_NONE: [Symbol; 4] = [*core, *option, *sym::Option, *sym::None];
pub static ref OPTION_SOME: [Symbol; 4] = [*core, *option, *sym::Option, *sym::Some];
pub static ref ORD: [Symbol; 3] = [*core, *cmp, *sym::Ord];
pub static ref OS_STRING: [Symbol; 4] = [*std, *ffi, *os_str, *OsString];
pub static ref OS_STR_TO_OS_STRING: [Symbol; 5] = [*std, *ffi, *os_str, *OsStr, *to_os_string];
pub static ref PARTIAL_ORD: [Symbol; 3] = [*core, *cmp, *sym::PartialOrd];
pub static ref PATH: [Symbol; 3] = [*std, *path, *Path];
pub static ref PATH_BUF: [Symbol; 3] = [*std, *path, *PathBuf];
pub static ref PATH_TO_PATH_BUF: [Symbol; 4] = [*std, *path, *Path, *to_path_buf];
pub static ref PTR_NULL: [Symbol; 2] = [*ptr, *null];
pub static ref PTR_NULL_MUT: [Symbol; 2] = [*ptr, *null_mut];
pub static ref RANGE: [Symbol; 3] = [*core, *ops, *Range];
pub static ref RANGE_ARGUMENT_TRAIT: [Symbol; 3] = [*core, *ops, *RangeBounds];
pub static ref RANGE_FROM: [Symbol; 3] = [*core, *ops, *RangeFrom];
pub static ref RANGE_FROM_STD: [Symbol; 3] = [*std, *ops, *RangeFrom];
pub static ref RANGE_FULL: [Symbol; 3] = [*core, *ops, *RangeFull];
pub static ref RANGE_FULL_STD: [Symbol; 3] = [*std, *ops, *RangeFull];
pub static ref RANGE_INCLUSIVE_NEW: [Symbol; 4] = [*core, *ops, *RangeInclusive, *new];
pub static ref RANGE_INCLUSIVE_STD_NEW: [Symbol; 4] = [*std, *ops, *RangeInclusive, *new];
pub static ref RANGE_STD: [Symbol; 3] = [*std, *ops, *Range];
pub static ref RANGE_TO: [Symbol; 3] = [*core, *ops, *RangeTo];
pub static ref RANGE_TO_INCLUSIVE: [Symbol; 3] = [*core, *ops, *RangeToInclusive];
pub static ref RANGE_TO_INCLUSIVE_STD: [Symbol; 3] = [*std, *ops, *RangeToInclusive];
pub static ref RANGE_TO_STD: [Symbol; 3] = [*std, *ops, *RangeTo];
pub static ref RC: [Symbol; 3] = [*alloc, *rc, *Rc];
pub static ref RECEIVER: [Symbol; 4] = [*std, *sync, *mpsc, *Receiver];
pub static ref REGEX: [Symbol; 3] = [*regex, *re_unicode, *Regex];
pub static ref REGEX_BUILDER_NEW: [Symbol; 5] = [*regex, *re_builder, *unicode, *RegexBuilder, *new];
pub static ref REGEX_BYTES_BUILDER_NEW: [Symbol; 5] = [*regex, *re_builder, *bytes, *RegexBuilder, *new];
pub static ref REGEX_BYTES_NEW: [Symbol; 4] = [*regex, *re_bytes, *Regex, *new];
pub static ref REGEX_BYTES_SET_NEW: [Symbol; 5] = [*regex, *re_set, *bytes, *RegexSet, *new];
pub static ref REGEX_NEW: [Symbol; 4] = [*regex, *re_unicode, *Regex, *new];
pub static ref REGEX_SET_NEW: [Symbol; 5] = [*regex, *re_set, *unicode, *RegexSet, *new];
pub static ref REPEAT: [Symbol; 3] = [*core, *iter, *repeat];
pub static ref RESULT: [Symbol; 3] = [*core, *result, *sym::Result];
pub static ref RESULT_ERR: [Symbol; 4] = [*core, *result, *sym::Result, *sym::Err];
pub static ref RESULT_OK: [Symbol; 4] = [*core, *result, *sym::Result, *sym::Ok];
pub static ref SERDE_DE_VISITOR: [Symbol; 3] = [*serde, *de, *Visitor];
pub static ref SLICE_INTO_VEC: [Symbol; 4] = [*alloc, *slice, *impl_slice_t, *into_vec];
pub static ref SLICE_ITER: [Symbol; 3] = [*core, *slice, *Iter];
pub static ref STD_MEM_TRANSMUTE: [Symbol; 3] = [*std, *mem, *transmute];
pub static ref STD_PTR_NULL: [Symbol; 3] = [*std, *ptr, *null];
pub static ref STRING: [Symbol; 3] = [*alloc, *string, *sym::String];
pub static ref TO_OWNED: [Symbol; 3] = [*alloc, *borrow, *sym::ToOwned];
pub static ref TO_OWNED_METHOD: [Symbol; 4] = [*alloc, *borrow, *sym::ToOwned, *to_owned];
pub static ref TO_STRING: [Symbol; 3] = [*alloc, *string, *sym::ToString];
pub static ref TO_STRING_METHOD: [Symbol; 4] = [*alloc, *string, *sym::ToString, *to_string];
pub static ref TRANSMUTE: [Symbol; 4] = [*core, *intrinsics, *empty_symbol, *transmute];
pub static ref TRY_INTO_RESULT: [Symbol; 4] = [*std, *ops, *Try, *into_result];
pub static ref UNINIT: [Symbol; 4] = [*core, *intrinsics, *empty_symbol, *uninit];
pub static ref VEC: [Symbol; 3] = [*alloc, *vec, *sym::Vec];
pub static ref VEC_DEQUE: [Symbol; 4] = [*alloc, *collections, *vec_deque, *VecDeque];
pub static ref VEC_FROM_ELEM: [Symbol; 3] = [*alloc, *vec, *from_elem];
pub static ref WEAK_ARC: [Symbol; 3] = [*alloc, *sync, *Weak];
pub static ref WEAK_RC: [Symbol; 3] = [*alloc, *rc, *Weak];
}

View File

@ -1,16 +1,18 @@
use crate::utils::{get_pat_name, match_var, snippet};
use crate::utils::sym;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::hir::*;
use rustc::lint::LateContext;
use std::borrow::Cow;
use syntax::ast::Name;
use syntax::source_map::Span;
use syntax::symbol::Symbol;
pub fn get_spans(
cx: &LateContext<'_, '_>,
opt_body_id: Option<BodyId>,
idx: usize,
replacements: &'static [(&'static str, &'static str)],
replacements: &[(Symbol, &'static str)],
) -> Option<Vec<(Span, Cow<'static, str>)>> {
if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
get_binding_name(&body.arguments[idx]).map_or_else(
@ -25,7 +27,7 @@ pub fn get_spans(
fn extract_clone_suggestions<'a, 'tcx: 'a>(
cx: &LateContext<'a, 'tcx>,
name: Name,
replace: &'static [(&'static str, &'static str)],
replace: &[(Symbol, &'static str)],
body: &'tcx Body,
) -> Option<Vec<(Span, Cow<'static, str>)>> {
let mut visitor = PtrCloneVisitor {
@ -46,7 +48,7 @@ fn extract_clone_suggestions<'a, 'tcx: 'a>(
struct PtrCloneVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
name: Name,
replace: &'static [(&'static str, &'static str)],
replace: &'a [(Symbol, &'static str)],
spans: Vec<(Span, Cow<'static, str>)>,
abort: bool,
}
@ -58,7 +60,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
}
if let ExprKind::MethodCall(ref seg, _, ref args) = expr.node {
if args.len() == 1 && match_var(&args[0], self.name) {
if seg.ident.name == "capacity" {
if seg.ident.name == *sym::capacity {
self.abort = true;
return;
}

View File

@ -0,0 +1,394 @@
#![allow(default_hash_types, non_upper_case_globals)]
use syntax::symbol::Symbol;
use lazy_static::lazy_static;
macro_rules! symbols_simple {
($($ident:ident,)*) => {
$(
lazy_static! {
pub(crate) static ref $ident: Symbol = Symbol::intern(stringify!($ident));
}
)*
};
}
macro_rules! symbols_init {
($($ident:ident: $expr:expr,)*) => {
$(
lazy_static! {
pub(crate) static ref $ident: Symbol = Symbol::intern($expr);
}
)*
};
}
// exists because concat_idents is flaky
pub mod assign {
pub(crate) use super::AddAssign as Add;
pub(crate) use super::SubAssign as Sub;
pub(crate) use super::MulAssign as Mul;
pub(crate) use super::DivAssign as Div;
pub(crate) use super::RemAssign as Rem;
pub(crate) use super::AndAssign as And;
pub(crate) use super::OrAssign as Or;
pub(crate) use super::BitAndAssign as BitAnd;
pub(crate) use super::BitOrAssign as BitOr;
pub(crate) use super::BitXorAssign as BitXor;
pub(crate) use super::ShrAssign as Shr;
pub(crate) use super::ShlAssign as Shl;
}
symbols_simple! {
Option,
rustc,
AsMut,
AsRef,
Clone,
Default,
DoubleEndedIterator,
Drop,
From,
Into,
IntoIterator,
Iterator,
Ord,
PartialOrd,
Any,
add,
Add,
AddAssign,
AndAssign,
OrAssign,
all,
alloc,
always,
any,
Arc,
Arguments,
array,
as_bytes,
as_mut,
as_ref,
assert,
as_str,
automatically_derived,
begin_panic,
begin_panic_fmt,
binary_heap,
BinaryHeap,
bitand,
BitAndAssign,
bitor,
BitOrAssign,
bitxor,
BitXorAssign,
bool,
borrow,
Borrow,
borrow_mut,
btree,
BTreeMap,
BTreeSet,
by_ref,
bytes,
capacity,
cfg,
cfg_attr,
chain,
chars,
clone,
cloned,
cmp,
collect,
collections,
conf_file,
contains,
contains_key,
context,
convert,
core,
count,
Cow,
c_str,
CString,
cycle,
dbg,
de,
debug_assert,
default,
deprecated,
deref,
Deref,
deref_mut,
discriminant,
Display,
div,
Div,
DivAssign,
doc,
drop,
Duration,
E,
EarlyContext,
end,
ends_with,
Entry,
enumerate,
eq,
Err,
extend,
ffi,
filter,
filter_map,
find,
flat_map,
fmt,
fold,
for_each,
forget,
format,
FRAC_1_PI,
FRAC_1_SQRT_2,
FRAC_2_PI,
FRAC_2_SQRT_PI,
FRAC_PI_2,
FRAC_PI_3,
FRAC_PI_4,
FRAC_PI_6,
FRAC_PI_8,
from,
from_elem,
from_iter,
from_str,
fs,
fuse,
hash,
Hash,
HashMap,
HashSet,
hidden,
i128,
i16,
i32,
i64,
i8,
Implied,
index,
Index,
index_mut,
IndexMut,
init,
inline,
insert,
inspect,
into_iter,
into_result,
into_vec,
intrinsics,
io,
is_empty,
is_err,
isize,
is_none,
is_ok,
is_some,
iter,
Iter,
iterator,
iter_mut,
last,
LateContext,
len,
linked_list,
LinkedList,
lint,
Lint,
LintPass,
LN_10,
LN_2,
LOG10_E,
LOG2_E,
macro_use,
main,
map,
matches,
match_indices,
max,
MAX,
max_by,
max_by_key,
mem,
min,
MIN,
min_by,
min_by_key,
mpsc,
mul,
Mul,
MulAssign,
mutex,
Mutex,
NAN,
ne,
neg,
new,
new_v1,
new_v1_formatted,
next,
next_back,
None,
not,
null,
null_mut,
offset,
ok,
Ok,
ONCE_INIT,
open,
OpenOptions,
ops,
option,
os_str,
OsStr,
OsString,
panic,
panicking,
partition,
path,
Path,
PathBuf,
paths,
peekable,
PI,
position,
precision,
print,
println,
proc_macro,
proc_macro_attribute,
proc_macro_derive,
product,
ptr,
push,
Range,
RangeBounds,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
rc,
Rc,
Read,
re_builder,
re_bytes,
Receiver,
regex,
Regex,
RegexBuilder,
RegexSet,
rem,
RemAssign,
repeat,
replace,
re_set,
resize,
result,
Result,
re_unicode,
rev,
rfind,
rmatches,
rmatch_indices,
rplit_terminator,
rposition,
rsplit,
rsplitn,
rsplit_terminator,
rustfmt,
rustfmt_skip,
scan,
serde,
set,
shl,
ShlAssign,
shr,
ShrAssign,
since,
skip,
skip_while,
slice,
Some,
split,
splitn,
split_terminator,
SQRT_2,
start,
starts_with,
std,
stderr,
stdin,
stdio,
stdout,
string,
String,
sub,
Sub,
SubAssign,
sum,
sync,
take,
take_while,
test,
time,
to_os_string,
to_owned,
ToOwned,
to_path_buf,
to_string,
ToString,
traits,
transmute,
trim_end_matches,
trim_start_matches,
Try,
u128,
u16,
u32,
u64,
u8,
unicode,
unimplemented,
uninit,
uninitialized,
unreachable,
unused_extern_crates,
unused_imports,
unwrap,
unwrap_err,
unzip,
usize,
utils,
vec,
Vec,
vec_deque,
VecDeque,
Visitor,
Weak,
width,
with_capacity,
wrapping_offset,
write,
Write,
write_fmt,
writeln,
zeroed,
zip,
}
symbols_init! {
impl_slice_t: "<impl [T]>",
empty_symbol: "",
}

View File

@ -1,10 +1,11 @@
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg};
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, sym};
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use std::borrow::Cow;
use syntax::ast::*;
use syntax::parse::{parser, token};
use syntax::symbol::Symbol;
use syntax::tokenstream::{TokenStream, TokenTree};
declare_clippy_lint! {
@ -181,7 +182,7 @@ declare_lint_pass!(Write => [
impl EarlyLintPass for Write {
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
if mac.node.path == "println" {
if mac.node.path == *sym::println {
span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
if fmtstr == "" {
@ -196,7 +197,7 @@ impl EarlyLintPass for Write {
);
}
}
} else if mac.node.path == "print" {
} else if mac.node.path == *sym::print {
span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
if let (Some(fmtstr), _, is_raw) = check_tts(cx, &mac.node.tts, false) {
if check_newlines(&fmtstr, is_raw) {
@ -209,7 +210,7 @@ impl EarlyLintPass for Write {
);
}
}
} else if mac.node.path == "write" {
} else if mac.node.path == *sym::write {
if let (Some(fmtstr), _, is_raw) = check_tts(cx, &mac.node.tts, true) {
if check_newlines(&fmtstr, is_raw) {
span_lint(
@ -221,7 +222,7 @@ impl EarlyLintPass for Write {
);
}
}
} else if mac.node.path == "writeln" {
} else if mac.node.path == *sym::writeln {
let check_tts = check_tts(cx, &mac.node.tts, true);
if let Some(fmtstr) = check_tts.0 {
if fmtstr == "" {
@ -364,7 +365,9 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
match arg.position {
ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
ArgumentNamed(name) => {
if *p == name {
// FIXME: remove this interning if possible
// https://github.com/rust-lang/rust/issues/60795
if *p == Symbol::intern(name) {
seen = true;
all_simple &= arg.format == SIMPLE;
}

View File

@ -125,7 +125,7 @@ fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDesc
base: config.src_base.clone(),
relative_dir: dir_path.file_name().unwrap().into(),
};
let test_name = compiletest::make_test_name(&config, &paths);
let test_name = compiletest::make_test_name(&config, &*paths);
let index = tests
.iter()
.position(|test| test.desc.name == test_name)