Fix adjacent code

This commit is contained in:
Samuel Moelius 2022-10-01 04:56:55 -04:00
parent 8611a0bb5c
commit 2e5e3560e9
17 changed files with 108 additions and 98 deletions

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::eq_expr_value;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{eq_expr_value, get_trait_def_id, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -483,7 +483,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
let ty = cx.typeck_results().expr_ty(expr); let ty = cx.typeck_results().expr_ty(expr);
get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])) cx.tcx
.get_diagnostic_item(sym::Ord)
.map_or(false, |id| implements_trait(cx, ty, id, &[]))
} }
struct NotSimplificationVisitor<'a, 'tcx> { struct NotSimplificationVisitor<'a, 'tcx> {

View file

@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{get_trait_def_id, if_sequence, in_constant, is_else_clause, paths, SpanlessEq}; use clippy_utils::{if_sequence, in_constant, is_else_clause, SpanlessEq};
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -106,7 +107,10 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
// Check that the type being compared implements `core::cmp::Ord` // Check that the type being compared implements `core::cmp::Ord`
let ty = cx.typeck_results().expr_ty(lhs1); let ty = cx.typeck_results().expr_ty(lhs1);
let is_ord = get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])); let is_ord = cx
.tcx
.get_diagnostic_item(sym::Ord)
.map_or(false, |id| implements_trait(cx, ty, id, &[]));
if !is_ord { if !is_ord {
return; return;

View file

@ -7,14 +7,14 @@ use rustc_middle::{
lint::in_external_macro, lint::in_external_macro,
ty::{self, Ty}, ty::{self, Ty},
}; };
use rustc_span::{sym, Span}; use rustc_span::{sym, Span, Symbol};
use clippy_utils::attrs::is_proc_macro; use clippy_utils::attrs::is_proc_macro;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_must_use_ty; use clippy_utils::ty::is_must_use_ty;
use clippy_utils::visitors::for_each_expr; use clippy_utils::visitors::for_each_expr;
use clippy_utils::{match_def_path, return_ty, trait_ref_of_method}; use clippy_utils::{return_ty, trait_ref_of_method};
use core::ops::ControlFlow; use core::ops::ControlFlow;
@ -181,7 +181,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
} }
} }
static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool { fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
match *ty.kind() { match *ty.kind() {
@ -189,7 +189,9 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
ty::Adt(adt, substs) => { ty::Adt(adt, substs) => {
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
|| KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did(), path)) || KNOWN_WRAPPER_TYS
.iter()
.any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
&& substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
}, },
ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)), ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)),

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{is_must_use_ty, match_type}; use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, match_type};
use clippy_utils::{is_must_use_func_call, paths}; use clippy_utils::{is_must_use_func_call, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::{Local, PatKind}; use rustc_hir::{Local, PatKind};
@ -7,6 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Symbol};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -99,10 +100,9 @@ declare_clippy_lint! {
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]); declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]);
const SYNC_GUARD_PATHS: [&[&str]; 6] = [ const SYNC_GUARD_SYMS: [Symbol; 3] = [sym::MutexGuard, sym::RwLockReadGuard, sym::RwLockWriteGuard];
&paths::MUTEX_GUARD,
&paths::RWLOCK_READ_GUARD, const SYNC_GUARD_PATHS: [&[&str]; 3] = [
&paths::RWLOCK_WRITE_GUARD,
&paths::PARKING_LOT_MUTEX_GUARD, &paths::PARKING_LOT_MUTEX_GUARD,
&paths::PARKING_LOT_RWLOCK_READ_GUARD, &paths::PARKING_LOT_RWLOCK_READ_GUARD,
&paths::PARKING_LOT_RWLOCK_WRITE_GUARD, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD,
@ -121,7 +121,10 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
let init_ty = cx.typeck_results().expr_ty(init); let init_ty = cx.typeck_results().expr_ty(init);
let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() { let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => { GenericArgKind::Type(inner_ty) => {
SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)) SYNC_GUARD_SYMS
.iter()
.any(|&sym| is_type_diagnostic_item(cx, inner_ty, sym))
|| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
}, },
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,

View file

@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::has_iter_method; use clippy_utils::ty::has_iter_method;
use clippy_utils::visitors::is_local_used; use clippy_utils::visitors::is_local_used;
use clippy_utils::{contains_name, higher, is_integer_const, match_trait_method, paths, sugg, SpanlessEq}; use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::ast; use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -302,8 +302,13 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if_chain! { if_chain! {
// a range index op // a range index op
if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind; if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX)) if let Some(trait_id) = self
|| (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); .cx
.typeck_results()
.type_dependent_def_id(expr.hir_id)
.and_then(|def_id| self.cx.tcx.trait_of_item(def_id));
if (meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id))
|| (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id));
if !self.check(args_1, args_0, expr); if !self.check(args_1, args_0, expr);
then { return } then { return }
} }

View file

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::match_function_call; use clippy_utils::match_function_call_with_def_id;
use clippy_utils::paths::FUTURE_FROM_GENERATOR;
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -175,7 +174,11 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
if_chain! { if_chain! {
if let Some(block_expr) = block.expr; if let Some(block_expr) = block.expr;
if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR); if let Some(args) = cx
.tcx
.lang_items()
.from_generator_fn()
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
if args.len() == 1; if args.len() == 1;
if let Expr{kind: ExprKind::Closure(&Closure { body, .. }), ..} = args[0]; if let Expr{kind: ExprKind::Closure(&Closure { body, .. }), ..} = args[0];
let closure_body = cx.tcx.hir().body(body); let closure_body = cx.tcx.hir().body(body);

View file

@ -12,9 +12,9 @@ use std::ops::Deref;
use clippy_utils::{ use clippy_utils::{
diagnostics::{span_lint_and_then, span_lint_hir_and_then}, diagnostics::{span_lint_and_then, span_lint_hir_and_then},
eq_expr_value, get_trait_def_id, eq_expr_value,
higher::If, higher::If,
is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, paths, peel_blocks, is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, peel_blocks,
peel_blocks_with_stmt, peel_blocks_with_stmt,
sugg::Sugg, sugg::Sugg,
ty::implements_trait, ty::implements_trait,
@ -190,7 +190,11 @@ impl TypeClampability {
fn is_clampable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<TypeClampability> { fn is_clampable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<TypeClampability> {
if ty.is_floating_point() { if ty.is_floating_point() {
Some(TypeClampability::Float) Some(TypeClampability::Float)
} else if get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])) { } else if cx
.tcx
.get_diagnostic_item(sym::Ord)
.map_or(false, |id| implements_trait(cx, ty, id, &[]))
{
Some(TypeClampability::Ord) Some(TypeClampability::Ord)
} else { } else {
None None

View file

@ -1,14 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{expr_block, snippet}; use clippy_utils::source::{expr_block, snippet};
use clippy_utils::ty::{implements_trait, match_type, peel_mid_ty_refs}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
use clippy_utils::{ use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
is_lint_allowed, is_unit_expr, is_wild, paths, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs,
};
use core::cmp::max; use core::cmp::max;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind}; use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::sym;
use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
@ -156,10 +155,10 @@ fn pat_in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'a>, pat: &Pat<'_>) ->
/// Returns `true` if the given type is an enum we know won't be expanded in the future /// Returns `true` if the given type is an enum we know won't be expanded in the future
fn in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'_>) -> bool { fn in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'_>) -> bool {
// list of candidate `Enum`s we know will never get any more members // list of candidate `Enum`s we know will never get any more members
let candidates = [&paths::COW, &paths::OPTION, &paths::RESULT]; let candidates = [sym::Cow, sym::Option, sym::Result];
for candidate_ty in candidates { for candidate_ty in candidates {
if match_type(cx, ty, candidate_ty) { if is_type_diagnostic_item(cx, ty, candidate_ty) {
return true; return true;
} }
} }

View file

@ -102,9 +102,7 @@ use bind_instead_of_map::BindInsteadOfMap;
use clippy_utils::consts::{constant, Constant}; use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::ty::{contains_adt_constructor, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::ty::{contains_adt_constructor, implements_trait, is_copy, is_type_diagnostic_item};
use clippy_utils::{ use clippy_utils::{contains_return, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty};
contains_return, get_trait_def_id, is_trait_method, iter_input_pats, meets_msrv, msrvs, paths, return_ty,
};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
@ -3846,12 +3844,12 @@ impl SelfKind {
return m == mutability && t == parent_ty; return m == mutability && t == parent_ty;
} }
let trait_path = match mutability { let trait_sym = match mutability {
hir::Mutability::Not => &paths::ASREF_TRAIT, hir::Mutability::Not => sym::AsRef,
hir::Mutability::Mut => &paths::ASMUT_TRAIT, hir::Mutability::Mut => sym::AsMut,
}; };
let Some(trait_def_id) = get_trait_def_id(cx, trait_path) else { let Some(trait_def_id) = cx.tcx.get_diagnostic_item(trait_sym) else {
return false return false
}; };
implements_trait(cx, ty, trait_def_id, &[parent_ty.into()]) implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])

View file

@ -32,8 +32,7 @@ pub(super) fn check<'tcx>(
return; return;
} }
let deref_aliases: [&[&str]; 9] = [ let deref_aliases: [&[&str]; 8] = [
&paths::DEREF_TRAIT_METHOD,
&paths::DEREF_MUT_TRAIT_METHOD, &paths::DEREF_MUT_TRAIT_METHOD,
&paths::CSTRING_AS_C_STR, &paths::CSTRING_AS_C_STR,
&paths::OS_STRING_AS_OS_STR, &paths::OS_STRING_AS_OS_STR,
@ -45,12 +44,14 @@ pub(super) fn check<'tcx>(
]; ];
let is_deref = match map_arg.kind { let is_deref = match map_arg.kind {
hir::ExprKind::Path(ref expr_qpath) => cx hir::ExprKind::Path(ref expr_qpath) => {
.qpath_res(expr_qpath, map_arg.hir_id) cx.qpath_res(expr_qpath, map_arg.hir_id)
.opt_def_id() .opt_def_id()
.map_or(false, |fun_def_id| { .map_or(false, |fun_def_id| {
deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path)) cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
}), || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
})
},
hir::ExprKind::Closure(&hir::Closure { body, .. }) => { hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let closure_body = cx.tcx.hir().body(body); let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(closure_body.value); let closure_expr = peel_blocks(closure_body.value);
@ -68,7 +69,8 @@ pub(super) fn check<'tcx>(
if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
then { then {
let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap(); let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
|| deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
} else { } else {
false false
} }

View file

@ -1,14 +1,14 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::eager_or_lazy::switch_to_lazy_eval; use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
use clippy_utils::source::{snippet, snippet_with_macro_callsite}; use clippy_utils::source::{snippet, snippet_with_macro_callsite};
use clippy_utils::ty::{implements_trait, match_type}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths}; use clippy_utils::{contains_return, is_trait_item, last_path_segment};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{kw, sym, Symbol};
use std::borrow::Cow; use std::borrow::Cow;
use super::OR_FUN_CALL; use super::OR_FUN_CALL;
@ -88,11 +88,11 @@ pub(super) fn check<'tcx>(
fun_span: Option<Span>, fun_span: Option<Span>,
) { ) {
// (path, fn_has_argument, methods, suffix) // (path, fn_has_argument, methods, suffix)
const KNOW_TYPES: [(&[&str], bool, &[&str], &str); 4] = [ const KNOW_TYPES: [(Symbol, bool, &[&str], &str); 4] = [
(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), (sym::BTreeEntry, false, &["or_insert"], "with"),
(&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"), (sym::HashMapEntry, false, &["or_insert"], "with"),
(&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"), (sym::Option, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
(&paths::RESULT, true, &["or", "unwrap_or"], "else"), (sym::Result, true, &["or", "unwrap_or"], "else"),
]; ];
if_chain! { if_chain! {
@ -104,7 +104,7 @@ pub(super) fn check<'tcx>(
let self_ty = cx.typeck_results().expr_ty(self_expr); let self_ty = cx.typeck_results().expr_ty(self_expr);
if let Some(&(_, fn_has_arguments, poss, suffix)) = if let Some(&(_, fn_has_arguments, poss, suffix)) =
KNOW_TYPES.iter().find(|&&i| match_type(cx, self_ty, i.0)); KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0));
if poss.contains(&name); if poss.contains(&name);

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{self, get_trait_def_id, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
let ty = cx.typeck_results().expr_ty(left); let ty = cx.typeck_results().expr_ty(left);
let implements_ord = { let implements_ord = {
if let Some(id) = get_trait_def_id(cx, &paths::ORD) { if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) {
implements_trait(cx, ty, id, &[]) implements_trait(cx, ty, id, &[])
} else { } else {
return; return;

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{match_any_def_paths, path_def_id, paths}; use clippy_utils::{match_def_path, path_def_id, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -49,13 +49,15 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
(arg, arg.span) (arg, arg.span)
}, },
ExprKind::Call(path, [arg]) ExprKind::Call(path, [arg])
if path_def_id(cx, path) if path_def_id(cx, path).map_or(false, |id| {
.and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM])) if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
.map_or(false, |idx| match idx { true
0 => true, } else if cx.tcx.lang_items().from_fn() == Some(id) {
1 => !is_copy(cx, typeck.expr_ty(expr)), !is_copy(cx, typeck.expr_ty(expr))
_ => false, } else {
}) => false
}
}) =>
{ {
(arg, arg.span) (arg, arg.span)
}, },

View file

@ -1,5 +1,4 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::{get_trait_def_id, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
@ -7,7 +6,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{BytePos, Span}; use rustc_span::{sym, BytePos, Span};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -80,7 +79,7 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
let fn_sig = cx.tcx.fn_sig(def_id); let fn_sig = cx.tcx.fn_sig(def_id);
let generics = cx.tcx.predicates_of(def_id); let generics = cx.tcx.predicates_of(def_id);
let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait()); let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait());
let ord_preds = get_trait_predicates_for_trait_id(cx, generics, get_trait_def_id(cx, &paths::ORD)); let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord));
let partial_ord_preds = let partial_ord_preds =
get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait()); get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait());
// Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error // Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error

View file

@ -1766,6 +1766,7 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool
/// ```rust,ignore /// ```rust,ignore
/// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX); /// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
/// ``` /// ```
/// This function is deprecated. Use [`match_function_call_with_def_id`].
pub fn match_function_call<'tcx>( pub fn match_function_call<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>,
@ -1783,6 +1784,22 @@ pub fn match_function_call<'tcx>(
None None
} }
pub fn match_function_call_with_def_id<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
fun_def_id: DefId,
) -> Option<&'tcx [Expr<'tcx>]> {
if_chain! {
if let ExprKind::Call(fun, args) = expr.kind;
if let ExprKind::Path(ref qpath) = fun.kind;
if cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id);
then {
return Some(args);
}
};
None
}
/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if /// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
/// any. /// any.
/// ///

View file

@ -16,25 +16,17 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"]; pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"];
pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"];
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"]; pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
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 BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"]; pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"]; pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"];
pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"]; pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"]; pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
pub const CORE_ITER_INTO_ITER: [&str; 6] = ["core", "iter", "traits", "collect", "IntoIterator", "into_iter"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; 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"]; 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 DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
@ -42,30 +34,22 @@ pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]
pub const EXIT: [&str; 3] = ["std", "process", "exit"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"];
pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl 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_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"]; pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"]; pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"];
pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"]; pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"]; pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"]; pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"];
pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"]; pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"]; pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"]; pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"]; pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"]; pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"]; pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
@ -76,13 +60,7 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"]; pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
/// Preferably use the diagnostic item `sym::Option` where possible
pub const OPTION: [&str; 3] = ["core", "option", "Option"];
pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"];
pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"];
pub const ORD: [&str; 3] = ["core", "cmp", "Ord"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
@ -95,8 +73,6 @@ pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
#[cfg_attr(not(unix), allow(clippy::invalid_paths))] #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"]; pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"]; pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"]; pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
@ -125,14 +101,8 @@ pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
/// Preferably use the diagnostic item `sym::Result` where possible
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const RUSTC_VERSION: [&str; 2] = ["rustc_semver", "RustcVersion"]; pub const RUSTC_VERSION: [&str; 2] = ["rustc_semver", "RustcVersion"];
pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"];
pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];

View file

@ -1,5 +1,5 @@
#![warn(clippy::internal)] #![warn(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)] #![allow(clippy::missing_clippy_version_attribute, clippy::unnecessary_def_path)]
mod paths { mod paths {
// Good path // Good path