From e122bf40f96d0cf7709dcfab57ad949ecc8f5f71 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Thu, 9 Sep 2021 10:23:06 -0400 Subject: [PATCH] Fix internal lint checking `match_type` uses * Check for `is_item` instead * Check consts and statics from external crates * Check for lang items * Check for inherent functions which have the same name as a field --- clippy_lints/src/drop_forget_ref.rs | 11 +- clippy_lints/src/duration_subsec.rs | 9 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/lib.rs | 8 +- .../src/loops/while_let_on_iterator.rs | 11 +- clippy_lints/src/mem_discriminant.rs | 5 +- clippy_lints/src/mem_forget.rs | 5 +- clippy_lints/src/mem_replace.rs | 6 +- clippy_lints/src/methods/filetype_is_file.rs | 5 +- .../src/methods/inefficient_to_string.rs | 4 +- clippy_lints/src/methods/manual_str_repeat.rs | 8 +- .../src/methods/uninit_assumed_init.rs | 7 +- clippy_lints/src/minmax.rs | 5 +- .../src/non_octal_unix_permissions.rs | 3 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/redundant_clone.rs | 4 +- clippy_lints/src/size_of_in_element_count.rs | 5 +- .../src/slow_vector_initialization.rs | 4 +- clippy_lints/src/to_string_in_display.rs | 6 +- clippy_lints/src/types/borrowed_box.rs | 5 +- clippy_lints/src/useless_conversion.rs | 4 +- clippy_lints/src/utils/internal_lints.rs | 190 ++++++++++++------ clippy_lints/src/verbose_file_reads.rs | 6 +- clippy_utils/src/lib.rs | 4 +- clippy_utils/src/paths.rs | 16 -- tests/ui-internal/auxiliary/paths.rs | 2 + tests/ui-internal/is_item_def_path.fixed | 43 ++++ tests/ui-internal/is_item_def_path.rs | 43 ++++ tests/ui-internal/is_item_def_path.stderr | 73 +++++++ 29 files changed, 352 insertions(+), 144 deletions(-) create mode 100644 tests/ui-internal/auxiliary/paths.rs create mode 100644 tests/ui-internal/is_item_def_path.fixed create mode 100644 tests/ui-internal/is_item_def_path.rs create mode 100644 tests/ui-internal/is_item_def_path.stderr diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 5a175c9d4abe..688e77134478 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,11 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::is_item; use clippy_utils::ty::is_copy; -use clippy_utils::{is_item, paths}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -124,10 +125,10 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { let arg_ty = cx.typeck_results().expr_ty(arg); if let ty::Ref(..) = arg_ty.kind() { - if is_item(cx, def_id, &paths::DROP) { + if is_item(cx, def_id, sym::mem_drop) { lint = DROP_REF; msg = DROP_REF_SUMMARY.to_string(); - } else if is_item(cx, def_id, &paths::MEM_FORGET) { + } else if is_item(cx, def_id, sym::mem_forget) { lint = FORGET_REF; msg = FORGET_REF_SUMMARY.to_string(); } else { @@ -140,10 +141,10 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { Some(arg.span), &format!("argument has type `{}`", arg_ty)); } else if is_copy(cx, arg_ty) { - if is_item(cx, def_id, &paths::DROP) { + if is_item(cx, def_id, sym::mem_drop) { lint = DROP_COPY; msg = DROP_COPY_SUMMARY.to_string(); - } else if is_item(cx, def_id, &paths::MEM_FORGET) { + } else if is_item(cx, def_id, sym::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 ecd4b3ff7015..763b77df5da2 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,3 +1,5 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_item; use clippy_utils::source::snippet_with_applicability; use if_chain::if_chain; @@ -6,10 +8,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; - -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::paths; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -45,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for DurationSubsec { if_chain! { if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind; if let ExprKind::MethodCall(method_path, _ , args, _) = left.kind; - if is_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), &paths::DURATION); + if is_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::Duration); if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right); then { let suggested_fn = match (method_path.ident.as_str().as_ref(), divisor) { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 6ca65271f0a6..1ec94da61a50 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e), ExprKind::Call(path, _) => { if let ExprKind::Path(ref qpath) = path.kind { - is_item(cx, (qpath, path.hir_id), &paths::ITER_REPEAT).into() + is_item(cx, (qpath, path.hir_id), sym::iter_repeat).into() } else { Finite } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 92a13be81f41..d5e9cd9b0ffa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -519,9 +519,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: #[cfg(feature = "internal-lints")] utils::internal_lints::INVALID_PATHS, #[cfg(feature = "internal-lints")] - utils::internal_lints::LINT_WITHOUT_LINT_PASS, + utils::internal_lints::IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM, #[cfg(feature = "internal-lints")] - utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + utils::internal_lints::LINT_WITHOUT_LINT_PASS, #[cfg(feature = "internal-lints")] utils::internal_lints::OUTER_EXPN_EXPN_DATA, #[cfg(feature = "internal-lints")] @@ -1170,8 +1170,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(utils::internal_lints::IF_CHAIN_STYLE), LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL), LintId::of(utils::internal_lints::INVALID_PATHS), + LintId::of(utils::internal_lints::IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM), LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS), - LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM), LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA), LintId::of(utils::internal_lints::PRODUCE_ICE), LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR), @@ -1846,7 +1846,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(utils::internal_lints::InvalidPaths)); store.register_late_pass(|| Box::new(utils::internal_lints::InterningDefinedSymbol::default())); store.register_late_pass(|| Box::new(utils::internal_lints::LintWithoutLintPass::default())); - store.register_late_pass(|| Box::new(utils::internal_lints::MatchTypeOnDiagItem)); + store.register_late_pass(|| Box::new(utils::internal_lints::IsItemDefPath)); store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass)); } diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index e4ba9a04724e..82eb712a37da 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -2,13 +2,11 @@ use super::WHILE_LET_ON_ITERATOR; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{ - get_enclosing_loop_or_closure, is_item, is_refutable, is_trait_method, paths, visitors::is_res_used, -}; +use clippy_utils::{get_enclosing_loop_or_closure, is_lang_ctor, is_refutable, is_trait_method, visitors::is_res_used}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}; -use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp}; +use rustc_hir::{def::Res, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp}; use rustc_lint::LateContext; use rustc_span::{symbol::sym, Span, Symbol}; @@ -16,9 +14,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (scrutinee_expr, iter_expr, some_pat, loop_expr) = if_chain! { if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr); // check for `Some(..)` pattern - if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind; - if let Res::Def(_, pat_did) = pat_path.res; - if is_item(cx, pat_did, &paths::OPTION_SOME); + if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind; + if is_lang_ctor(cx, pat_path, LangItem::OptionSome); // check for call to `Iterator::next` if let ExprKind::MethodCall(method_name, _, [iter_expr], _) = let_expr.kind; if method_name.ident.name == sym::next; diff --git a/clippy_lints/src/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index 356cf9513638..b01ce69b3cb0 100644 --- a/clippy_lints/src/mem_discriminant.rs +++ b/clippy_lints/src/mem_discriminant.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_item; use clippy_utils::source::snippet; use clippy_utils::ty::walk_ptrs_ty_depth; -use clippy_utils::{is_item, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -37,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { // is `mem::discriminant` if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if is_item(cx, def_id, &paths::MEM_DISCRIMINANT); + if is_item(cx, def_id, sym::mem_discriminant); // type is non-enum let ty_param = cx.typeck_results().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 05b19e4e2b9b..c0cd3a05422d 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -1,8 +1,9 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_item, paths}; +use clippy_utils::is_item; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -31,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for MemForget { if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if is_item(cx, def_id, &paths::MEM_FORGET) { + if is_item(cx, def_id, sym::mem_forget) { let forgot_ty = cx.typeck_results().expr_ty(first_arg); 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 f61b80fd5ae4..860500e1d864 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{in_macro, is_default_equivalent, is_item, is_lang_ctor, meets_msrv, msrvs, paths}; +use clippy_utils::{in_macro, is_default_equivalent, is_item, is_lang_ctor, meets_msrv, msrvs}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; @@ -11,7 +11,7 @@ use rustc_middle::lint::in_external_macro; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use rustc_span::symbol::sym; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { if let ExprKind::Call(func, func_args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if is_item(cx, def_id, &paths::MEM_REPLACE); + if is_item(cx, def_id, sym::mem_replace); if let [dest, src] = func_args; then { check_replace_option_with_none(cx, src, dest, expr.span); diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs index 42bb4ed5d6b8..778f00cc40e3 100644 --- a/clippy_lints/src/methods/filetype_is_file.rs +++ b/clippy_lints/src/methods/filetype_is_file.rs @@ -1,17 +1,18 @@ use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::get_parent_expr; use clippy_utils::is_item; -use clippy_utils::{get_parent_expr, paths}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::source_map::Span; +use rustc_span::sym; use super::FILETYPE_IS_FILE; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { let ty = cx.typeck_results().expr_ty(recv); - if !is_item(cx, ty, &paths::FILE_TYPE) { + if !is_item(cx, ty, sym::FileType) { return; } diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index 38883971e756..afb4385155ae 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{sym, Symbol}; use super::INEFFICIENT_TO_STRING; @@ -60,7 +60,7 @@ fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } if let ty::Adt(adt, substs) = ty.kind() { - is_item(cx, adt.did, &paths::COW) && substs.type_at(1).is_str() + is_item(cx, adt.did, sym::Cow) && substs.type_at(1).is_str() } else { false } diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 415f63ef8eef..43777cc56539 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -1,14 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_item; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; -use clippy_utils::{is_item, paths}; use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TyS}; -use rustc_span::symbol::sym; +use rustc_span::sym; use std::borrow::Cow; use super::MANUAL_STR_REPEAT; @@ -37,7 +37,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { let ty = cx.typeck_results().expr_ty(e); if is_item(cx, ty, sym::string_type) || (is_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, TyS::is_str)) - || (is_item(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, TyS::is_str)) + || (is_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, TyS::is_str)) { Some(RepeatKind::String) } else { @@ -56,7 +56,7 @@ pub(super) fn check( ) { if_chain! { if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind; - if is_item(cx, repeat_fn, &paths::ITER_REPEAT); + if is_item(cx, repeat_fn, sym::iter_repeat); if is_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::string_type); if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id); if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id); diff --git a/clippy_lints/src/methods/uninit_assumed_init.rs b/clippy_lints/src/methods/uninit_assumed_init.rs index e6a2600e3e74..fc9fa2a0cdf1 100644 --- a/clippy_lints/src/methods/uninit_assumed_init.rs +++ b/clippy_lints/src/methods/uninit_assumed_init.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_item, paths}; +use clippy_utils::is_item; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; +use rustc_span::sym; use super::UNINIT_ASSUMED_INIT; @@ -12,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr if_chain! { if let hir::ExprKind::Call(callee, args) = recv.kind; if args.is_empty(); - if is_item(cx, callee, &paths::MEM_MAYBEUNINIT_UNINIT); + if is_item(cx, callee, sym::maybe_uninit_uninit); if !is_maybe_uninit_ty_valid(cx, cx.typeck_results().expr_ty_adjusted(expr)); then { span_lint( @@ -29,7 +30,7 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { match ty.kind() { ty::Array(component, _) => is_maybe_uninit_ty_valid(cx, component), ty::Tuple(types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), - ty::Adt(adt, _) => is_item(cx, adt.did, &paths::MEM_MAYBEUNINIT), + ty::Adt(adt, _) => is_item(cx, adt.did, hir::LangItem::MaybeUninit), _ => false, } } diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index e3468a9afad4..98b286376afd 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -5,6 +5,7 @@ use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; use std::cmp::Ordering; declare_clippy_lint! { @@ -73,9 +74,9 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons .qpath_res(qpath, path.hir_id) .opt_def_id() .and_then(|def_id| { - if is_item(cx, def_id, &paths::CMP_MIN) { + if is_item(cx, def_id, sym::cmp_min) { fetch_const(cx, args, MinMax::Min) - } else if is_item(cx, def_id, &paths::CMP_MAX) { + } else if is_item(cx, def_id, sym::cmp_max) { fetch_const(cx, args, MinMax::Max) } else { None diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs index f620e7088974..1d82101f85fb 100644 --- a/clippy_lints/src/non_octal_unix_permissions.rs +++ b/clippy_lints/src/non_octal_unix_permissions.rs @@ -6,6 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -47,7 +48,7 @@ impl LateLintPass<'_> for NonOctalUnixPermissions { if_chain! { if (path.ident.name == sym!(mode) && (is_item(cx, obj_ty, &paths::OPEN_OPTIONS) - || is_item(cx, obj_ty, &paths::DIR_BUILDER))) + || is_item(cx, obj_ty, sym::DirBuilder))) || (path.ident.name == sym!(set_mode) && is_item(cx, obj_ty, &paths::PERMISSIONS)); if let ExprKind::Lit(_) = param.kind; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a7fc01a81a24..e37c31ad06c1 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -337,7 +337,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: }, ); } - } else if is_item(cx, ty, &paths::COW) { + } else if is_item(cx, ty, sym::Cow) { if_chain! { if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind; if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind; diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index e6b543638593..3ca0658ce57a 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{def_id, Body, FnDecl, HirId}; +use rustc_hir::{def_id, Body, FnDecl, HirId, LangItem}; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::{ @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { } if let ty::Adt(def, _) = arg_ty.kind() { - if is_item(cx, def.did, &paths::MEM_MANUALLY_DROP) { + if is_item(cx, def.did, LangItem::ManuallyDrop) { continue; } } diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index 76b42ccb29fd..691e9db326ae 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -9,6 +9,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty, TyS, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -43,8 +44,8 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) if !inverted; if let ExprKind::Path(ref count_func_qpath) = count_func.kind; if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id(); - if is_item(cx, def_id, &paths::MEM_SIZE_OF) - || is_item(cx, def_id, &paths::MEM_SIZE_OF_VAL); + if is_item(cx, def_id, sym::mem_size_of) + || is_item(cx, def_id, sym::mem_size_of_val); then { cx.typeck_results().node_substs(count_func.hir_id).types().next() } else { diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 1df61f8f1f83..4b976f487cf5 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_enclosing_block, is_item, path_to_local, path_to_local_id, paths, SpanlessEq}; +use clippy_utils::{get_enclosing_block, is_item, path_to_local, path_to_local_id, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -254,7 +254,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool { if_chain! { if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind; - if is_item(self.cx, fn_expr, &paths::ITER_REPEAT); + if is_item(self.cx, fn_expr, sym::iter_repeat); if let ExprKind::Lit(ref lit) = repeat_arg.kind; if let LitKind::Int(0, _) = lit.node; diff --git a/clippy_lints/src/to_string_in_display.rs b/clippy_lints/src/to_string_in_display.rs index 3b3f00055924..3133028a7d2b 100644 --- a/clippy_lints/src/to_string_in_display.rs +++ b/clippy_lints/src/to_string_in_display.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::{is_diag_trait_item, is_item, path_to_local_id, paths}; +use clippy_utils::{is_diag_trait_item, is_item, path_to_local_id}; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::sym; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -114,7 +114,7 @@ fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind; if let Some(did) = trait_ref.trait_def_id(); then { - is_item(cx, did, &paths::DISPLAY_TRAIT) + is_item(cx, did, sym::display_trait) } else { false } diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index 6491219698fd..3fa991ad0b04 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_item; use clippy_utils::source::snippet; -use clippy_utils::{is_item, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -8,6 +8,7 @@ use rustc_hir::{ SyntheticTyParamKind, TyKind, }; use rustc_lint::LateContext; +use rustc_span::sym; use super::BORROWED_BOX; @@ -91,7 +92,7 @@ fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { if let Some(trait_did) = traits[0].trait_ref.trait_def_id(); // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. - if is_item(cx, trait_did, &paths::ANY_TRAIT); + if is_item(cx, trait_did, sym::Any); then { return true; } diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 428b751598aa..1a09de8739e7 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::same_type_and_consts; use clippy_utils::{get_parent_expr, is_item, is_trait_method, paths}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; +use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } if_chain! { - if is_item(cx, def_id, &paths::FROM_FROM); + if is_item(cx, def_id, LangItem::FromFrom); if same_type_and_consts(a, b); then { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 070a05031b05..9f062863f8c9 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -3,7 +3,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug use clippy_utils::higher; use clippy_utils::source::snippet; use clippy_utils::{ - is_else_clause, is_expn_of, is_item, is_lint_allowed, method_calls, path_to_res, paths, SpanlessEq, + is_else_clause, is_expn_of, is_item, is_lint_allowed, method_calls, path_to_res, paths, peel_hir_expr_refs, + SpanlessEq, }; use if_chain::if_chain; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId}; @@ -16,13 +17,13 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{ - BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty, - TyKind, UnOp, + BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, TyKind, + UnOp, }; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; -use rustc_middle::mir::interpret::ConstValue; -use rustc_middle::ty; +use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{Symbol, SymbolStr}; @@ -30,6 +31,7 @@ use rustc_span::{BytePos, Span}; use rustc_typeck::hir_ty_to_ty; use std::borrow::{Borrow, Cow}; +use std::str; #[cfg(feature = "metadata-collector-lint")] pub mod metadata_collector; @@ -226,10 +228,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for calls to `clippy_utils::is_item()` taking a path to a diagnostic item. + /// Checks for calls to `clippy_utils::is_item()` taking a path to a diagnostic or lang item. /// /// ### Why is this bad? - /// Using diagnostic items doesn't require hard-coded paths. + /// Diagnostic or lang items don't require hard-coded paths. /// /// ### Example /// Bad: @@ -241,9 +243,9 @@ declare_clippy_lint! { /// ```rust,ignore /// clippy_utils::is_item(cx, ty, sym::vec_type) /// ``` - pub MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + pub IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM, internal, - "using `clippy_utils::is_item()` with a path to a diagnostic item" + "using `clippy_utils::is_item()` with a path to a diagnostic or lang item" } declare_clippy_lint! { @@ -436,7 +438,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { } } -fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool { +fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Rptr( _, MutTy { @@ -752,90 +754,146 @@ fn suggest_note( ); } -declare_lint_pass!(MatchTypeOnDiagItem => [MATCH_TYPE_ON_DIAGNOSTIC_ITEM]); +declare_lint_pass!(IsItemDefPath => [IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM]); -impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem { +impl<'tcx> LateLintPass<'tcx> for IsItemDefPath { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if is_lint_allowed(cx, MATCH_TYPE_ON_DIAGNOSTIC_ITEM, expr.hir_id) { + if is_lint_allowed(cx, IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM, expr.hir_id) { return; } if_chain! { - // Check if this is a call to utils::is_item() - if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind; - if is_item(cx, fn_path, &["clippy_utils", "is_item"]); + if let ExprKind::Call(func, [_, _, item_arg]) = expr.kind; + if is_item(cx, func, &["clippy_utils", "is_item"]); // Extract the path to the matched type - if let Some(segments) = path_to_matched_type(cx, ty_path); + if let Some(segments) = path_to_matched_type(cx, item_arg); let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect(); - if let Some(ty_did) = path_to_res(cx, &segments[..]).opt_def_id(); - // Check if the matched type is a diagnostic item - let diag_items = cx.tcx.diagnostic_items(ty_did.krate); - if let Some(item_name) = diag_items.iter().find_map(|(k, v)| if *v == ty_did { Some(k) } else { None }); + if let Some(def_id) = path_to_res(cx, &segments[..]).opt_def_id(); then { - // TODO: check paths constants from external crates. - let cx_snippet = snippet(cx, context.span, "_"); - let ty_snippet = snippet(cx, ty.span, "_"); + // path_to_res will match field names before anything else, but for this we want to match + // inherent functions first. + let def_id = if cx.tcx.def_kind(def_id) == DefKind::Field { + let method_name = *segments.last().unwrap(); + cx.tcx.def_key(def_id).parent + .and_then(|parent_idx| + cx.tcx.inherent_impls(DefId { index: parent_idx, krate: def_id.krate}).iter() + .flat_map(|impl_id| cx.tcx.item_children(*impl_id).iter()) + .find(|item| item.ident.name.as_str() == method_name) + ) + .and_then(|item| item.res.opt_def_id()) + .unwrap_or(def_id) + } else { + def_id + }; - span_lint_and_sugg( + let diag_items = cx.tcx.diagnostic_items(def_id.krate); + let (msg, replacement) = if let Some(item_name) = diag_items.iter() + .find_map(|(k, v)| if *v == def_id { Some(k) } else { None }) + { + ( + "usage of `clippy_utils::is_item()` with a path to a diagnostic item", + format!("sym::{}", item_name), + ) + } else if let Some(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) { + let lang_items = path_to_res(cx, &["rustc_hir", "lang_items", "LangItem"]).def_id(); + let item_name = cx.tcx.adt_def(lang_items).variants.iter().nth(lang_item).unwrap() + .ident.name.as_str(); + ( + "usage of `clippy_utils::is_item()` with a path to a lang item", + format!("LangItem::{}", item_name), + ) + } else { + return; + }; + span_lint_and_then( cx, - MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + IS_ITEM_DEF_PATH_ON_DIAGNOSTIC_OR_LANG_ITEM, expr.span, - "usage of `clippy_utils::is_item()` on a path to a diagnostic item", - "try", - format!("clippy_utils::is_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name), - Applicability::MaybeIncorrect, + msg, + |diag| { + diag.span_suggestion( + item_arg.span, + "try", + replacement, + Applicability::MachineApplicable, + ); + } ); } } } } -fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option> { - use rustc_hir::ItemKind; - - match &expr.kind { - ExprKind::AddrOf(.., expr) => return path_to_matched_type(cx, expr), - ExprKind::Path(qpath) => match cx.qpath_res(qpath, expr.hir_id) { +fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option> { + match peel_hir_expr_refs(expr).0.kind { + ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { let parent_id = cx.tcx.hir().get_parent_node(hir_id); - if let Some(Node::Local(local)) = cx.tcx.hir().find(parent_id) { - if let Some(init) = local.init { - return path_to_matched_type(cx, init); - } + if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) { + path_to_matched_type(cx, init) + } else { + None } }, - Res::Def(DefKind::Const | DefKind::Static, def_id) => { - if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) { - if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind { - let body = cx.tcx.hir().body(body_id); - return path_to_matched_type(cx, &body.value); - } - } + Res::Def(DefKind::Static, def_id) => { + read_mir_alloc_def_path(cx, cx.tcx.eval_static_initializer(def_id).ok()?, cx.tcx.type_of(def_id)) }, - _ => {}, + Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? { + ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => { + read_mir_alloc_def_path(cx, alloc, cx.tcx.type_of(def_id)) + }, + _ => None, + }, + _ => None, }, - ExprKind::Array(exprs) => { - let segments: Vec = exprs - .iter() - .filter_map(|expr| { - if let ExprKind::Lit(lit) = &expr.kind { - if let LitKind::Str(sym, _) = lit.node { - return Some(sym.as_str()); - } + ExprKind::Array(exprs) => exprs + .iter() + .map(|expr| { + if let ExprKind::Lit(lit) = &expr.kind { + if let LitKind::Str(sym, _) = lit.node { + return Some((*sym.as_str()).to_owned()); } + } - None - }) - .collect(); - - if segments.len() == exprs.len() { - return Some(segments); - } - }, - _ => {}, + None + }) + .collect(), + _ => None, } +} - None +fn read_mir_alloc_def_path(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option> { + let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() { + if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(*alloc.relocations().values().next()?) { + (alloc, ty) + } else { + return None; + } + } else { + (alloc, ty) + }; + + if_chain! { + if let ty::Array(ty, _) | ty::Slice(ty) = *ty.kind(); + if let ty::Ref(_, ty, Mutability::Not) = *ty.kind(); + if ty.is_str(); + then { + alloc + .relocations() + .values() + .map(|alloc| { + if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(*alloc) { + str::from_utf8(alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len())) + .ok().map(ToOwned::to_owned) + } else { + None + } + }) + .collect() + } else { + None + } + } } // This is not a complete resolver for paths. It works on all the paths currently used in the paths diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs index 74395033a07b..96cef0feaa39 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_item; -use clippy_utils::paths; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -64,7 +64,7 @@ fn is_file_read_to_end<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> if method_name.ident.as_str() == "read_to_end"; if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind; let ty = cx.typeck_results().expr_ty(&exprs[0]); - if is_item(cx, ty, &paths::FILE); + if is_item(cx, ty, sym::File); then { return true } @@ -78,7 +78,7 @@ fn is_file_read_to_string<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) if method_name.ident.as_str() == "read_to_string"; if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind; let ty = cx.typeck_results().expr_ty(&exprs[0]); - if is_item(cx, ty, &paths::FILE); + if is_item(cx, ty, sym::File); then { return true } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 735538a2c512..048c089d6799 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2115,7 +2115,7 @@ impl MaybeDefId for Ty<'_> { /// Currently the `DefId` can come from the following types /// * `DefId` /// * `Res` -/// * `(&QPath, HirId)` where the HirId is from the expression containing the path +/// * `(&QPath, HirId)` where the `HirId` is from the expression containing the path /// * `&Expr` /// * `&Pat` /// * `Ty<'_>` from `rustc_middle` @@ -2124,7 +2124,7 @@ impl MaybeDefId for Ty<'_> { /// And the item to check for can have the following types /// * `&[str]` for the absolute path to the item. See `clippy_utils::paths` /// * `LangItem` -/// & `sym` for diagnostic items +/// * `sym` for diagnostic items pub fn is_item(cx: &LateContext<'_>, id: impl MaybeDefId, item: impl ItemRef) -> bool { id.to_def_id(cx).map_or(false, |id| item.is_item(cx, id)) } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index d7e46c2d3eb9..03126a486ee9 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -4,7 +4,6 @@ //! Whenever possible, please consider diagnostic items over hardcoded paths. //! See for more information. -pub const ANY_TRAIT: [&str; 3] = ["core", "any", "Any"]; #[cfg(feature = "metadata-collector-lint")] pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"]; #[cfg(feature = "metadata-collector-lint")] @@ -27,26 +26,20 @@ pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", " pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"]; pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"]; 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_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; /// Preferably use the diagnostic item `sym::deref_method` where possible pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; -pub const DIR_BUILDER: [&str; 3] = ["std", "fs", "DirBuilder"]; pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; -pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; #[cfg(feature = "internal-lints")] pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "", "EPSILON"]; -pub const FILE: [&str; 3] = ["std", "fs", "File"]; -pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"]; pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"]; @@ -67,7 +60,6 @@ pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const IPADDR_V4: [&str; 5] = ["std", "net", "ip", "IpAddr", "V4"]; pub const IPADDR_V6: [&str; 5] = ["std", "net", "ip", "IpAddr", "V6"]; -pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"]; pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; #[cfg(feature = "internal-lints")] pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; @@ -76,14 +68,6 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; pub const LIBC_STRLEN: [&str; 2] = ["libc", "strlen"]; #[cfg(any(feature = "internal-lints", feature = "metadata-collector-lint"))] pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; -pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; -pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; -pub const MEM_MANUALLY_DROP: [&str; 4] = ["core", "mem", "manually_drop", "ManuallyDrop"]; -pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"]; -pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]; -pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; -pub const MEM_SIZE_OF: [&str; 3] = ["core", "mem", "size_of"]; -pub const MEM_SIZE_OF_VAL: [&str; 3] = ["core", "mem", "size_of_val"]; pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"]; pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OPS_MODULE: [&str; 2] = ["core", "ops"]; diff --git a/tests/ui-internal/auxiliary/paths.rs b/tests/ui-internal/auxiliary/paths.rs new file mode 100644 index 000000000000..52fcaec4df32 --- /dev/null +++ b/tests/ui-internal/auxiliary/paths.rs @@ -0,0 +1,2 @@ +pub static OPTION: [&str; 3] = ["core", "option", "Option"]; +pub const RESULT: &[&str] = &["core", "result", "Result"]; diff --git a/tests/ui-internal/is_item_def_path.fixed b/tests/ui-internal/is_item_def_path.fixed new file mode 100644 index 000000000000..ce892e021922 --- /dev/null +++ b/tests/ui-internal/is_item_def_path.fixed @@ -0,0 +1,43 @@ +// run-rustfix +// aux-build:paths.rs +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate clippy_utils; +extern crate paths; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +extern crate rustc_span; + +use clippy_utils::is_item; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; + +#[allow(unused)] +use rustc_hir::LangItem; +#[allow(unused)] +use rustc_span::sym; + +#[allow(unused)] +static OPTION: [&str; 3] = ["core", "option", "Option"]; +#[allow(unused)] +const RESULT: &[&str] = &["core", "result", "Result"]; + +fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) { + let _ = is_item(cx, ty, sym::option_type); + let _ = is_item(cx, ty, sym::result_type); + let _ = is_item(cx, ty, sym::result_type); + + #[allow(unused)] + let rc_path = &["alloc", "rc", "Rc"]; + let _ = clippy_utils::is_item(cx, ty, sym::Rc); + + let _ = is_item(cx, ty, sym::option_type); + let _ = is_item(cx, ty, sym::result_type); + + let _ = is_item(cx, ty, LangItem::OwnedBox); + let _ = is_item(cx, ty, sym::maybe_uninit_uninit); +} + +fn main() {} diff --git a/tests/ui-internal/is_item_def_path.rs b/tests/ui-internal/is_item_def_path.rs new file mode 100644 index 000000000000..323b059c1a79 --- /dev/null +++ b/tests/ui-internal/is_item_def_path.rs @@ -0,0 +1,43 @@ +// run-rustfix +// aux-build:paths.rs +#![deny(clippy::internal)] +#![feature(rustc_private)] + +extern crate clippy_utils; +extern crate paths; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +extern crate rustc_span; + +use clippy_utils::is_item; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; + +#[allow(unused)] +use rustc_hir::LangItem; +#[allow(unused)] +use rustc_span::sym; + +#[allow(unused)] +static OPTION: [&str; 3] = ["core", "option", "Option"]; +#[allow(unused)] +const RESULT: &[&str] = &["core", "result", "Result"]; + +fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) { + let _ = is_item(cx, ty, &OPTION); + let _ = is_item(cx, ty, RESULT); + let _ = is_item(cx, ty, &["core", "result", "Result"]); + + #[allow(unused)] + let rc_path = &["alloc", "rc", "Rc"]; + let _ = clippy_utils::is_item(cx, ty, rc_path); + + let _ = is_item(cx, ty, &paths::OPTION); + let _ = is_item(cx, ty, paths::RESULT); + + let _ = is_item(cx, ty, &["alloc", "boxed", "Box"]); + let _ = is_item(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); +} + +fn main() {} diff --git a/tests/ui-internal/is_item_def_path.stderr b/tests/ui-internal/is_item_def_path.stderr new file mode 100644 index 000000000000..db600be07687 --- /dev/null +++ b/tests/ui-internal/is_item_def_path.stderr @@ -0,0 +1,73 @@ +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:28:13 + | +LL | let _ = is_item(cx, ty, &OPTION); + | ^^^^^^^^^^^^^^^^-------^ + | | + | help: try: `sym::option_type` + | +note: the lint level is defined here + --> $DIR/is_item_def_path.rs:3:9 + | +LL | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(clippy::is_item_def_path_on_diagnostic_or_lang_item)]` implied by `#[deny(clippy::internal)]` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:29:13 + | +LL | let _ = is_item(cx, ty, RESULT); + | ^^^^^^^^^^^^^^^^------^ + | | + | help: try: `sym::result_type` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:30:13 + | +LL | let _ = is_item(cx, ty, &["core", "result", "Result"]); + | ^^^^^^^^^^^^^^^^-----------------------------^ + | | + | help: try: `sym::result_type` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:34:13 + | +LL | let _ = clippy_utils::is_item(cx, ty, rc_path); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^ + | | + | help: try: `sym::Rc` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:36:13 + | +LL | let _ = is_item(cx, ty, &paths::OPTION); + | ^^^^^^^^^^^^^^^^--------------^ + | | + | help: try: `sym::option_type` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:37:13 + | +LL | let _ = is_item(cx, ty, paths::RESULT); + | ^^^^^^^^^^^^^^^^-------------^ + | | + | help: try: `sym::result_type` + +error: usage of `clippy_utils::is_item()` with a path to a lang item + --> $DIR/is_item_def_path.rs:39:13 + | +LL | let _ = is_item(cx, ty, &["alloc", "boxed", "Box"]); + | ^^^^^^^^^^^^^^^^--------------------------^ + | | + | help: try: `LangItem::OwnedBox` + +error: usage of `clippy_utils::is_item()` with a path to a diagnostic item + --> $DIR/is_item_def_path.rs:40:13 + | +LL | let _ = is_item(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); + | ^^^^^^^^^^^^^^^^---------------------------------------------------------^ + | | + | help: try: `sym::maybe_uninit_uninit` + +error: aborting due to 8 previous errors +