From d4cc83857e8d331d40b8edf2898a9e468396475c Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Wed, 8 Sep 2021 12:28:21 -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 | 5 +- clippy_lints/src/duration_subsec.rs | 9 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/mem_discriminant.rs | 5 +- clippy_lints/src/mem_forget.rs | 5 +- clippy_lints/src/mem_replace.rs | 4 +- clippy_lints/src/methods/filetype_is_file.rs | 5 +- .../src/methods/inefficient_to_string.rs | 16 +- clippy_lints/src/methods/manual_str_repeat.rs | 29 ++- .../src/methods/uninit_assumed_init.rs | 7 +- clippy_lints/src/ptr.rs | 152 +++++--------- clippy_lints/src/redundant_clone.rs | 4 +- clippy_lints/src/size_of_in_element_count.rs | 4 +- .../src/slow_vector_initialization.rs | 4 +- clippy_lints/src/to_string_in_display.rs | 4 +- clippy_lints/src/types/borrowed_box.rs | 5 +- clippy_lints/src/utils/internal_lints.rs | 198 +++++++++++------- clippy_lints/src/verbose_file_reads.rs | 7 +- clippy_utils/src/paths.rs | 13 -- 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 +++++++ 24 files changed, 408 insertions(+), 239 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 eb0d218d1836..8b7053cd1c51 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::is_any_item; use clippy_utils::ty::is_copy; -use clippy_utils::{is_any_item, paths}; 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 @@ -116,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { if !(arg_ty.is_ref() || is_copy(cx, arg_ty)) { return; } - let (lint, msg) = match is_any_item(cx, path, &[paths::DROP.as_slice(), paths::MEM_FORGET.as_slice()]) { + let (lint, msg) = match is_any_item(cx, path, &[sym::mem_drop, sym::mem_forget]) { Some(0) if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY.to_string()), Some(0) => (DROP_COPY, DROP_COPY_SUMMARY.to_string()), Some(1) if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY.to_string()), diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index ecd4b3ff7015..96d36281a5f7 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -5,11 +5,10 @@ use rustc_errors::Applicability; 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 rustc_span::{source_map::Spanned, sym}; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::paths; declare_clippy_lint! { /// ### What it does @@ -44,8 +43,8 @@ impl<'tcx> LateLintPass<'tcx> for DurationSubsec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { 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 let ExprKind::MethodCall(method_path, _ , [self_arg], _) = left.kind; + if is_item(cx, cx.typeck_results().expr_ty(self_arg).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) { @@ -62,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DurationSubsec { "try", format!( "{}.{}()", - snippet_with_applicability(cx, args[0].span, "_", &mut applicability), + snippet_with_applicability(cx, self_arg.span, "_", &mut applicability), suggested_fn ), applicability, diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index c598c95558a2..a03139cf959c 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -165,7 +165,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { }, ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)), ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e), - ExprKind::Call(path, _) => is_item(cx, path, &paths::ITER_REPEAT).into(), + ExprKind::Call(path, _) => is_item(cx, path, sym::iter_repeat).into(), ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(), _ => Finite, } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 24ac10f3821d..606d947055b7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -520,9 +520,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")] @@ -1171,8 +1171,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), @@ -1847,7 +1847,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/mem_discriminant.rs b/clippy_lints/src/mem_discriminant.rs index b806313f750b..28135aaa1e71 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 @@ -35,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { if_chain! { if let ExprKind::Call(func, func_args) = expr.kind; // is `mem::discriminant` - if is_item(cx, func, &paths::MEM_DISCRIMINANT); + if is_item(cx, func, 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 b5055d2823a6..7d4a5bf82524 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 @@ -29,7 +30,7 @@ declare_lint_pass!(MemForget => [MEM_FORGET]); impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind { - if is_item(cx, path_expr, &paths::MEM_FORGET) { + if is_item(cx, path_expr, 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)) { span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type"); diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 81aed6966d22..e880ab8996d5 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; @@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { if_chain! { // Check that `expr` is a call to `mem::replace()` if let ExprKind::Call(func, [dest, src]) = expr.kind; - if is_item(cx, func, &paths::MEM_REPLACE); + if is_item(cx, func, sym::mem_replace); then { check_replace_option_with_none(cx, src, dest, expr.span); check_replace_with_uninit(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 ae743260e739..473c29647635 100644 --- a/clippy_lints/src/methods/filetype_is_file.rs +++ b/clippy_lints/src/methods/filetype_is_file.rs @@ -1,16 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{get_parent_expr, is_item, paths}; +use clippy_utils::{get_parent_expr, is_item}; 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 842be065ad46..41b098a875f4 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::walk_ptrs_ty_depth; -use clippy_utils::{is_item, paths}; +use clippy_utils::{is_any_item, is_item, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -50,11 +50,13 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy /// Returns whether `ty` specializes `ToString`. /// Currently, these are `str`, `String`, and `Cow<'_, str>`. fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { - if ty.is_str() || is_item(cx, ty, sym::string_type) { - true - } else if let ty::Adt(adt, substs) = ty.kind() { - is_item(cx, adt.did, &paths::COW) && substs.type_at(1).is_str() - } else { - false + match *ty.kind() { + ty::Str => true, + ty::Adt(adt, subs) => match is_any_item(cx, adt.did, &[sym::string_type, sym::Cow]) { + Some(0) => true, + Some(1) => subs.type_at(1).is_str(), + _ => false, + }, + _ => false, } } diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 156b9b8c6d6d..2af4b820a0db 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -1,13 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; -use clippy_utils::{is_item, paths}; +use clippy_utils::{is_any_item, is_item}; 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_middle::ty; use rustc_span::symbol::sym; use std::borrow::Cow; @@ -18,14 +18,6 @@ enum RepeatKind { Char(char), } -fn get_ty_param(ty: Ty<'_>) -> Option> { - if let ty::Adt(_, subs) = ty.kind() { - subs.types().next() - } else { - None - } -} - fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = &e.kind { match lit.node { @@ -34,11 +26,16 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { _ => None, } } else { - let ty = cx.typeck_results().expr_ty(e).peel_refs(); - (ty.is_str() - || 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))) + match cx.typeck_results().expr_ty(e).peel_refs().kind() { + ty::Str => true, + ty::Adt(adt, subs) if is_item(cx, adt.did, LangItem::OwnedBox) => subs.type_at(0).is_str(), + ty::Adt(adt, subs) => match is_any_item(cx, adt.did, &[sym::string_type, sym::Cow]) { + Some(0) => true, + Some(1) => subs.type_at(1).is_str(), + _ => false, + }, + _ => false, + } .then(|| RepeatKind::String) } } @@ -52,7 +49,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 e7c2580e68b5..05c9b90d4a6e 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; @@ -11,7 +12,7 @@ use super::UNINIT_ASSUMED_INIT; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if_chain! { if let hir::ExprKind::Call(callee, []) = recv.kind; - 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( @@ -28,7 +29,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/ptr.rs b/clippy_lints/src/ptr.rs index f52415b3639b..2338b50d2a31 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the use clippy_utils::ptr::get_spans; use clippy_utils::source::snippet_opt; use clippy_utils::ty::walk_ptrs_hir_ty; -use clippy_utils::{is_any_item, is_item, is_lint_allowed, paths}; +use clippy_utils::{is_any_item, is_lint_allowed, paths}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -245,8 +245,7 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { #[allow(clippy::too_many_lines)] fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option) { let fn_def_id = cx.tcx.hir().local_def_id(fn_id); - let sig = cx.tcx.fn_sig(fn_def_id); - let fn_ty = sig.skip_binder(); + let fn_ty = cx.tcx.fn_sig(fn_def_id).skip_binder(); let body = opt_body_id.map(|id| cx.tcx.hir().body(id)); for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { @@ -258,110 +257,69 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: } if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() { - if is_item(cx, ty, sym::vec_type) { - if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { - span_lint_and_then( - cx, - PTR_ARG, - arg.span, + let (msg, new_ty, replacements) = + match is_any_item(cx, ty, &[sym::vec_type, sym::string_type, sym::PathBuf, sym::Cow]) { + Some(0) => ( "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ with non-Vec-based slices", - |diag| { - if let Some(ref snippet) = get_only_generic_arg_snippet(cx, arg) { - diag.span_suggestion( - arg.span, - "change this to", - format!("&[{}]", snippet), - Applicability::Unspecified, - ); - } - for (clonespan, suggestion) in spans { - diag.span_suggestion( - clonespan, - &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { - Cow::Owned(format!("change `{}` to", x)) - }), - suggestion.into(), - Applicability::Unspecified, - ); - } - }, - ); - } - } else if is_item(cx, ty, sym::string_type) { - if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { - span_lint_and_then( - cx, - PTR_ARG, - arg.span, + get_only_generic_arg_snippet(cx, arg).map(|snip| format!("&[{}]", snip)), + [("clone", ".to_owned()")].as_slice(), + ), + Some(1) => ( "writing `&String` instead of `&str` involves a new object where a slice will do", - |diag| { - diag.span_suggestion(arg.span, "change this to", "&str".into(), Applicability::Unspecified); - for (clonespan, suggestion) in spans { - diag.span_suggestion_short( - clonespan, - &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { - Cow::Owned(format!("change `{}` to", x)) - }), - suggestion.into(), - Applicability::Unspecified, - ); - } - }, - ); - } - } else if is_item(cx, ty, sym::PathBuf) { - if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) { - span_lint_and_then( - cx, - PTR_ARG, - arg.span, + Some("&str".into()), + [("clone", ".to_string()"), ("as_str", "")].as_slice(), + ), + Some(2) => ( "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do", - |diag| { - diag.span_suggestion( - arg.span, - "change this to", - "&Path".into(), - Applicability::Unspecified, - ); - for (clonespan, suggestion) in spans { - diag.span_suggestion_short( - clonespan, - &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { - Cow::Owned(format!("change `{}` to", x)) - }), - suggestion.into(), + Some("&Path".into()), + [("clone", ".to_path_buf()"), ("as_path", "")].as_slice(), + ), + Some(3) => { + if_chain! { + if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind; + if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind; + if let [ref bx] = *pp.segments; + if let Some(params) = bx.args; + if !params.parenthesized; + if let Some(inner) = params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }); + let replacement = snippet_opt(cx, inner.span); + if let Some(r) = replacement; + then { + span_lint_and_sugg( + cx, + PTR_ARG, + arg.span, + "using a reference to `Cow` is not recommended", + "change this to", + "&".to_owned() + &r, Applicability::Unspecified, ); } - }, - ); - } - } else if is_item(cx, ty, &paths::COW) { - if_chain! { - if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind; - if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind; - if let [ref bx] = *pp.segments; - if let Some(params) = bx.args; - if !params.parenthesized; - if let Some(inner) = params.args.iter().find_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }); - let replacement = snippet_opt(cx, inner.span); - if let Some(r) = replacement; - then { - span_lint_and_sugg( - cx, - PTR_ARG, - arg.span, - "using a reference to `Cow` is not recommended", - "change this to", - "&".to_owned() + &r, + } + continue; + }, + _ => continue, + }; + if let Some(spans) = get_spans(cx, opt_body_id, idx, replacements) { + span_lint_and_then(cx, PTR_ARG, arg.span, msg, |diag| { + if let Some(new_ty) = new_ty { + diag.span_suggestion(arg.span, "change this to", new_ty, Applicability::Unspecified); + } + for (clonespan, suggestion) in spans { + diag.span_suggestion_short( + clonespan, + &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| { + Cow::Owned(format!("change `{}` to", x)) + }), + suggestion.into(), Applicability::Unspecified, ); } - } + }); } } } diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 669bfcf0b393..82c96e5567ab 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::{ @@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { _ => continue, }; - if is_item(cx, arg_ty, &paths::MEM_MANUALLY_DROP) { + if is_item(cx, arg_ty, 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 1bb4e584372f..b91ee3b7bacd 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 @@ -41,8 +42,7 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) ExprKind::Call(count_func, _func_args) => { if_chain! { if !inverted; - if is_any_item(cx, count_func, &[paths::MEM_SIZE_OF.as_slice(), paths::MEM_SIZE_OF_VAL.as_slice()]) - .is_some(); + if is_any_item(cx, count_func, &[sym::mem_size_of, sym::mem_size_of_val]).is_some(); 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 f07b8cea3062..36f3f7cde354 100644 --- a/clippy_lints/src/to_string_in_display.rs +++ b/clippy_lints/src/to_string_in_display.rs @@ -1,5 +1,5 @@ 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}; @@ -115,7 +115,7 @@ fn is_display_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { .. }) = &item.kind { - is_item(cx, trait_ref.trait_def_id(), &paths::DISPLAY_TRAIT) + is_item(cx, trait_ref.trait_def_id(), sym::display_trait) } else { false } diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index e6afb6c297cb..009165c3e38a 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; @@ -89,7 +90,7 @@ fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. if let TyKind::TraitObject([trait_, ..], ..) = t.kind; - if is_item(cx, trait_.trait_ref.trait_def_id(), &paths::ANY_TRAIT); + if is_item(cx, trait_.trait_ref.trait_def_id(), sym::Any); then { return true; } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 07347d84d7b1..e69d491cb43d 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_any_item, is_else_clause, is_expn_of, is_item, is_lint_allowed, method_calls, path_to_res, paths, SpanlessEq, + is_any_item, 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,25 +228,25 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for calls to `utils::match_type()` on a type diagnostic item - /// and suggests to use `utils::is_type_diagnostic_item()` instead. + /// Checks for calls to `clippy_utils::is_item()` comparing def paths when the item is either a + /// diagnostic or lang item. /// /// ### Why is this bad? - /// `utils::is_type_diagnostic_item()` does not require hardcoded paths. + /// Diagnostic or lang items don't require hardcoded paths. /// /// ### Example /// Bad: /// ```rust,ignore - /// utils::match_type(cx, ty, &paths::VEC) + /// clippy_utils::is_item(cx, ty, &paths::VEC) /// ``` /// /// Good: /// ```rust,ignore - /// utils::is_type_diagnostic_item(cx, ty, sym::vec_type) + /// 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 `utils::match_type()` instead of `utils::is_type_diagnostic_item()`" + "using `clippy_utils::is_same()` on a def path for a diagnostic or lang item" } declare_clippy_lint! { @@ -437,7 +439,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 { @@ -746,94 +748,150 @@ fn suggest_note( note_span, note ), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } -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::match_type() - if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind; - if is_item(cx, fn_path, &["clippy_utils", "ty", "match_type"]); + 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()` on a def path which is 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()` on a def path which is 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::ty::match_type()` on a type diagnostic item", - "try", - format!("clippy_utils::ty::is_type_diagnostic_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 aa1abd2fd7a9..75265d3f91d7 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_item, paths}; +use clippy_utils::is_item; 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 @@ -63,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, _)) = self_arg.kind; let ty = cx.typeck_results().expr_ty(self_arg); - if is_item(cx, ty, &paths::FILE); + if is_item(cx, ty, sym::File); then { return true } @@ -77,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, _)) = self_arg.kind; let ty = cx.typeck_results().expr_ty(self_arg); - if is_item(cx, ty, &paths::FILE); + if is_item(cx, ty, sym::File); then { return true } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 98dbf4bc5a76..931066d535bf 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")] @@ -37,14 +36,11 @@ 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"]; @@ -65,7 +61,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"]; @@ -73,14 +68,6 @@ pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"]; #[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..d30f8c3153e6 --- /dev/null +++ b/tests/ui-internal/is_item_def_path.stderr @@ -0,0 +1,73 @@ +error: usage of `clippy_utils::is_item()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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()` on a def path which is 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 +