diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 6b327cf6191cc..c831729091274 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,10 +1,13 @@ use crate::utils::span_lint; +use crate::utils::sym; +use lazy_static::lazy_static; 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; declare_clippy_lint! { /// **What it does:** Checks for floating point literals that approximate @@ -30,38 +33,40 @@ 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]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ApproxConstant { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { if let ExprKind::Lit(lit) = &e.node { - check_lit(cx, lit, e); + check_lit(cx, &lit.node, e); } } } -fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) { - match lit.node { +fn check_lit(cx: &LateContext<'_, '_>, lit: &LitKind, e: &Expr) { + match *lit { LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"), LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"), LitKind::FloatUnsuffixed(s) => check_known_consts(cx, e, s, "f{32, 64}"), @@ -72,7 +77,7 @@ fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) { fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) { let s = s.as_str(); if s.parse::().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, diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 0f0c0dbc15d05..1690c10e29158 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -5,6 +5,7 @@ use rustc::{declare_lint_pass, declare_tool_lint}; use syntax_pos::Span; use crate::consts::{constant, Constant}; +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, is_direct_expn_of, span_help_and_lint}; declare_clippy_lint! { @@ -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); diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 6d938687fa27f..ff34cb3d998a9 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -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 { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 9a9279a409ae3..754dc3a06ae7b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,9 +1,10 @@ //! checks for attributes use crate::reexport::*; +use crate::utils::sym; 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, + in_macro_or_desugar, is_present_in_source, last_line_of_span, match_def_path, paths, snippet_opt, span_lint, + span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; use rustc::hir::*; @@ -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,17 @@ 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 +399,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 +445,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 +477,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 +491,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; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 5c19e232bc984..f58b17e9a29db 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,7 +1,9 @@ +use crate::utils::sym; 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 lazy_static::lazy_static; use rustc::hir::intravisit::*; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -10,6 +12,7 @@ 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; 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, &[])) } diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 5716927be03e4..e9b0ae6797c4d 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{ contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg, walk_ptrs_ty, @@ -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] diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 9374e04bc11ea..bc2542fa3a620 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -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); } } diff --git a/clippy_lints/src/const_static_lifetime.rs b/clippy_lints/src/const_static_lifetime.rs index a69771b8b8096..150d379cc7c7a 100644 --- a/clippy_lints/src/const_static_lifetime.rs +++ b/clippy_lints/src/const_static_lifetime.rs @@ -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, ""); let sugg = format!("&{}", snip); span_lint_and_then( diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index 79e30f1a7d8aa..fe24ff1cfc0a7 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -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, diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index c54bafae56a1b..637e19bd60e32 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{snippet_opt, span_help_and_lint, span_lint_and_sugg}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; @@ -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, diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 8597835d8050f..ba1312add7464 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -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, match_def_path, paths, span_lint_and_sugg}; 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(..) => { diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index bf2845af13367..66bf1a3566fa0 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -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; } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 51be83a8a0677..f55cf7246b4e3 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -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, spans.extend_from_slice(¤t_spans); doc.push_str(¤t); } - } else if attr.check_name("doc") { + } else if attr.check_name(*sym::doc) { // ignore mix of sugared and non-sugared doc return; } diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index 89e405c93670e..61009cc633950 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -1,4 +1,4 @@ -use crate::utils::{paths, span_lint}; +use crate::utils::{match_def_path, paths, span_lint}; 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, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index e36e7353a57ac..a6dcb51fcae83 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_copy, paths, span_note_and_lint}; +use crate::utils::{is_copy, match_def_path, paths, span_note_and_lint}; 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 { diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 60470ede5419d..79c9e88589111 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -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) { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 551e0bb848d8b..66ae2966dfbb5 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::SpanlessEq; use crate::utils::{get_item_name, higher, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; @@ -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 = ¶ms[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, ¶ms[0]); if SpanlessEq::new(self.cx).eq_expr(self.key, ¶ms[1]); then { diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index a29b1380006c2..11f2770333fb0 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_expn_of, resolve_node, span_lint, span_lint_and_sugg}; +use crate::utils::sym; +use crate::utils::{is_expn_of, match_def_path, paths, resolve_node, span_lint, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -31,21 +32,20 @@ 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_fun_id) = resolve_node(cx, qpath, dest_fun.hir_id).opt_def_id(); + if let Some(dest_name) = if match_def_path(cx, dest_fun_id, &*paths::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, &*paths::STDERR) { Some("stderr") } else { None @@ -54,9 +54,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 diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 6e97857131e60..ee1b888cb07d5 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,10 +1,12 @@ 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::sym; +use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; 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::symbol::Symbol; use syntax_pos::Span; declare_clippy_lint! { @@ -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, } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index ace059f842887..cb9e486a7093c 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -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, + in_macro_or_desugar, is_expn_of, last_path_segment, match_def_path, match_type, resolve_node, snippet, + span_lint_and_then, walk_ptrs_ty, }; 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; } diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 61d287fbea62d..5d15eb3341b37 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -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, + in_macro_or_desugar, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, + span_lint_and_then, }; 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) { diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index dc5a3a6b2f732..368aeb4424f74 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, is_expn_of, snippet_opt, span_lint_and_then}; use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, MatchSource}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -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") } }, diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 29e0396c09e30..6d5c1375bc4f1 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -2,7 +2,10 @@ use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; +use crate::utils::sym; use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; +use lazy_static::lazy_static; +use syntax::symbol::Symbol; 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; 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]); diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 5242b22c79082..0e998b44c21fd 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -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; } diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs index 677b20999360a..9641e9f9e4bc2 100644 --- a/clippy_lints/src/invalid_ref.rs +++ b/clippy_lints/src/invalid_ref.rs @@ -1,4 +1,4 @@ -use crate::utils::{paths, span_help_and_lint}; +use crate::utils::{match_def_path, paths, span_help_and_lint}; 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 { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index f464ebd03ddf0..131f0301c424f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{ get_item_name, in_macro_or_desugar, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; @@ -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,8 @@ 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 +153,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 +172,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 +184,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 +194,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,12 +216,12 @@ 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; } } - check_len(cx, span, method_path.ident.name, args, lit, op, compare_to) + check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to) } } @@ -227,21 +230,17 @@ fn check_len( span: Span, method_name: Name, args: &[Expr], - lit: &Lit, + lit: &LitKind, op: &str, compare_to: u32, ) { - if let Spanned { - node: LitKind::Int(lit, _), - .. - } = *lit - { + if let LitKind::Int(lit, _) = *lit { // check if length is compared to the specified number if lit != u128::from(compare_to) { 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, @@ -265,7 +264,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 diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0f09f678e4bb8..da413cd12ced4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -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`.) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index e868adee7eb55..ff75fbaa55f22 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -476,7 +476,9 @@ 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; } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f47d2e45d6fad..9280461548cf4 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -10,6 +10,7 @@ use rustc::middle::region; use rustc::{declare_lint_pass, declare_tool_lint}; // use rustc::middle::region::CodeExtent; use crate::consts::{constant, Constant}; +use crate::utils::sym; use crate::utils::usage::mutated_variables; use crate::utils::{in_macro_or_desugar, sext, sugg}; use rustc::middle::expr_use_visitor::*; @@ -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,10 @@ 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 +815,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 { @@ -874,7 +878,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( ) -> Option { 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 +984,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 +1226,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 +1354,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 +1382,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 +1402,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 +1418,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 +1531,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 +1811,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 +1967,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 +2415,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 +2435,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 +2446,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| { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index df10336d6d972..80cfde7cac561 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -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 { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 2e97f44b317f7..5318badf36c63 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -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]); } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index cb33ad4d974b8..fb290ee3ac80e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,6 +1,7 @@ use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::sugg::Sugg; +use crate::utils::sym; use crate::utils::{ expr_block, in_macro_or_desugar, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, @@ -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) -> 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 { 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; diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 296954972b1ca..2ce56647ac748 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -1,4 +1,4 @@ -use crate::utils::{paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; +use crate::utils::{match_def_path, paths, snippet, span_lint_and_then, walk_ptrs_ty_depth}; 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(); diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index d4c6471916729..3f314d332823e 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,4 +1,4 @@ -use crate::utils::{paths, span_lint}; +use crate::utils::{match_def_path, paths, span_lint}; 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)) { diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index ee4780c10e6ec..2649fd6a519f7 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,4 +1,4 @@ -use crate::utils::{match_qpath, paths, snippet_with_applicability, span_lint_and_sugg}; +use crate::utils::{match_def_path, match_qpath, paths, snippet_with_applicability, span_lint_and_sugg}; 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), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f8cde663d899a..3e093cf31094e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -6,6 +6,7 @@ use std::fmt; use std::iter; use if_chain::if_chain; +use lazy_static::lazy_static; use matches::matches; use rustc::hir; use rustc::hir::def::{DefKind, Res}; @@ -15,15 +16,16 @@ 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 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, + is_ctor_function, is_expn_of, is_self, is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, + match_qpath, match_trait_method, match_type, 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, }; @@ -905,20 +907,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 +958,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 +1032,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 +1067,8 @@ 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::().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::().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::().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,33 @@ 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 +2274,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); @@ -2285,14 +2306,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)> { +fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: Ty<'_>) -> 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 +2328,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 +2350,7 @@ fn lint_into_iter(cx: &LateContext<'_, '_>, expr: &hir::Expr, self_ref_ty: Ty<'_ /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option> { 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 +2385,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 +2497,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 +2514,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 +2618,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 } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 9a8880a7960a7..ec95f1ee571b3 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -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 diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index a28e6fa88bbe7..31bea83f5a5b8 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -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), } } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 1e99fffbddf98..5a9634571272f 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,5 +1,5 @@ use crate::consts::{constant_simple, Constant}; -use crate::utils::{paths, span_lint}; +use crate::utils::{match_def_path, paths, span_lint}; 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 diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index b7479122ea9ce..66a5ac6824f78 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -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,8 @@ 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; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 0cce9ddbc7b67..94c8e7ff709c2 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -5,6 +5,7 @@ // [`missing_doc`]: https://github.com/rust-lang/rust/blob/d6d05904697d89099b55da3331155392f1db9c00/src/librustc_lint/builtin.rs#L246 // +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, span_lint}; use if_chain::if_chain; use rustc::hir; @@ -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) { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 2c887eb54d08c..835e856026f6b 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -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, diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 3b9641b354f2a..380844c44db31 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -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!( diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 294a17d80bbb3..461e5885476b2 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -2,6 +2,7 @@ //! //! This lint is **warn** by default +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, snippet_opt, span_lint_and_then}; use if_chain::if_chain; use rustc::hir::{BindingAnnotation, Expr, ExprKind, HirId, Item, MutImmutable, Pat, PatKind}; @@ -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); } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ce8f1a0ec5520..9c380e34aa678 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -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)) }) diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index e05a953b30608..7cc1b576cfa80 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -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; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 55a4b1588c2b2..7e2899bc7a989 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -1,5 +1,6 @@ use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; +use crate::utils::sym; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then}; use if_chain::if_chain; use rustc::hir; @@ -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(); diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index b1d180c6ceb37..12976e05b087e 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{span_lint, span_lint_and_then}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, impl_lint_pass}; @@ -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, diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 01d41f679dbb3..c097f17d30e29 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint}; use if_chain::if_chain; use rustc::hir::*; @@ -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.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, diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index 062534333c23e..fa3e589d92b75 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -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 { diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 57ff7536a3867..8f896acbd3d3d 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,4 +1,5 @@ -use crate::utils::{is_direct_expn_of, is_expn_of, paths, resolve_node, span_lint}; +use crate::utils::sym; +use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, paths, resolve_node, span_lint}; 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('{'); diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 8f4b785339d99..3e146a72ab86b 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{is_automatically_derived, span_lint_hir}; use if_chain::if_chain; use rustc::hir::*; @@ -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, diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs index ce9947298fa50..3234c81de23ee 100644 --- a/clippy_lints/src/path_buf_push_overwrite.rs +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{match_type, paths, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc::hir::*; @@ -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; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index af69d62ddb739..8a6933b2f5a4f 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -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,13 @@ 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 +220,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 +299,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); } } } diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 2d3c3298f5847..f33347c8cb206 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -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)); } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 743c0c4224a2f..1949101def9e9 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,7 +8,8 @@ use syntax::ptr::P; use crate::utils::paths::*; use crate::utils::sugg::Sugg; -use crate::utils::{higher, match_type, span_lint_and_then, SpanlessEq}; +use crate::utils::sym; +use crate::utils::{higher, match_def_path, match_type, span_lint_and_then, SpanlessEq}; 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 diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index a18ee4c2b896e..d5e71fdbec326 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -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,8 @@ 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> { diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 8c86c27befdfa..53bfc15a509b5 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -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, + has_drop, in_macro_or_desugar, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir, + span_lint_hir_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; use matches::matches; @@ -94,13 +94,14 @@ 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 +134,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 { diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index fe1a29b98833c..9f47883724057 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -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, 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> { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 4a437cbcf944f..59b1cc016712c 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -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::sym; +use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; 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); } } diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 2130a65ad9446..80ea39a301c04 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -1,10 +1,13 @@ -use crate::utils::span_lint_and_sugg; +use crate::utils::sym; +use crate::utils::{match_def_path, span_lint_and_sugg}; use if_chain::if_chain; +use lazy_static::lazy_static; 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; 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()"), ]; +} diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 8d1873b8a18de..0764a96e263e4 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -7,6 +7,7 @@ use syntax::source_map::Span; use syntax::visit::FnKind; use syntax_pos::BytePos; +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint}; declare_clippy_lint! { @@ -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 diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index bb4ebf63066b3..37eb2dd494260 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -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; diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 0bc992b3191b8..d84602c5c78d0 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -1,4 +1,5 @@ use crate::utils::sugg::Sugg; +use crate::utils::sym; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use if_chain::if_chain; use rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; @@ -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; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 0adeec93e69c2..b6b0ca822c811 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -4,6 +4,7 @@ use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Spanned; +use crate::utils::sym; use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -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""#); diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index d869285eb5899..ecc033937ab58 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,9 +1,11 @@ +use crate::utils::sym; use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method}; 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 { 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); diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index fc5b2150d52cf..cb3a9465a77ea 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -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)); } } diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index a13b0102fd980..45d80e3f5e3a2 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -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, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg}; 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); diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs index a5bb05dc64184..90623d531adc7 100644 --- a/clippy_lints/src/transmuting_null.rs +++ b/clippy_lints/src/transmuting_null.rs @@ -1,5 +1,5 @@ use crate::consts::{constant_context, Constant}; -use crate::utils::{match_qpath, span_lint}; +use crate::utils::{match_qpath, paths, 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( diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 8205851d77572..3dffcc7361bf7 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -1,5 +1,6 @@ use std::cmp; +use crate::utils::sym; use crate::utils::{in_macro_or_desugar, is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; use matches::matches; @@ -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; } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 4aa3b75dec2e7..cf637ceb70686 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -18,13 +18,15 @@ 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::sym; 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, + match_def_path, 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, }; declare_clippy_lint! { @@ -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!( diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index b3de0823bd453..b807a62efccd5 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -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, diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 0ec7256d4b3a6..9949a086f93aa 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -2,6 +2,7 @@ use if_chain::if_chain; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; +use crate::utils::sym; use crate::utils::{ higher::if_block, in_macro_or_desugar, match_type, paths, span_lint_and_then, usage::is_potentially_mutated, }; @@ -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 { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 6e371c9fe5ff6..1c71a76f15905 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -2,6 +2,7 @@ #![deny(clippy::missing_docs_in_private_items)] +use crate::utils::sym; use lazy_static::lazy_static; use std::default::Default; use std::io::Read; @@ -13,7 +14,7 @@ use toml; /// Gets the configuration file from arguments. pub fn file_from_args(args: &[ast::NestedMetaItem]) -> Result, (&'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)) diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 5c9f5e25f4d84..610d0c932169b 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -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::sym; +use crate::utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; 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> { /// 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(name: Symbol, fields: &[hir::Field]) -> Option<&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,8 @@ 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 +118,30 @@ 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 +238,14 @@ pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr) -> Option [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") { + fn check_crate(&mut self, _cx: &EarlyContext<'_>, _krate: &AstCrate) { + /* + FIXME: turn back on when we get rid of all the lazy_statics + 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 = 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 { @@ -100,6 +101,7 @@ impl EarlyLintPass for ClippyLintsInternal { } } } + */ } } @@ -121,7 +123,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 +181,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 +235,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, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index bfc1233f9eba5..e08a83dd54c15 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -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 { +pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[Symbol]) -> Option { 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, 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> { +pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[Symbol]) -> Option> { 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 { +pub fn is_expn_of(mut span: Span, name: Symbol) -> Option { loop { let span_name_span = span .ctxt() @@ -708,7 +709,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `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 { +pub fn is_direct_expn_of(span: Span, name: Symbol) -> Option { 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 { // FIXME: instead of this hard-coded list, we should check if `::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 { + 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) +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 9ee25aaea5ead..46c2de74d7203 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,111 +1,123 @@ //! 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", "", "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 lazy_static::lazy_static; +use syntax::symbol::Symbol; + +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 STDERR: [Symbol; 4] = [*std, *io, *stdio, *stderr]; + pub static ref STDOUT: [Symbol; 4] = [*std, *io, *stdio, *stdout]; + 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]; +} diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 3d221fbfb81d9..a0096b2a653b8 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,3 +1,4 @@ +use crate::utils::sym; use crate::utils::{get_pat_name, match_var, snippet}; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::*; @@ -5,12 +6,13 @@ 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, idx: usize, - replacements: &'static [(&'static str, &'static str)], + replacements: &[(Symbol, &'static str)], ) -> Option)>> { 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)>> { 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; } diff --git a/clippy_lints/src/utils/sym.rs b/clippy_lints/src/utils/sym.rs new file mode 100644 index 0000000000000..263d2d42ff4ff --- /dev/null +++ b/clippy_lints/src/utils/sym.rs @@ -0,0 +1,393 @@ +#![allow(default_hash_types, non_upper_case_globals)] + +use lazy_static::lazy_static; +use syntax::symbol::Symbol; + +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::AndAssign as And; + 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::DivAssign as Div; + pub(crate) use super::MulAssign as Mul; + pub(crate) use super::OrAssign as Or; + pub(crate) use super::RemAssign as Rem; + pub(crate) use super::ShlAssign as Shl; + pub(crate) use super::ShrAssign as Shr; + pub(crate) use super::SubAssign as Sub; +} + +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: "", + empty_symbol: "", +} diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 9f4ebdec71432..5c9fc943492c4 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -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; }