Replace all item identification utils (#15682)

This introduces a new way of identifying items/paths using extension
traits with a composable set of functions rather than unique functions
for various combinations of starting points and target items. Altogether
this is a set of five traits:

* `MaybeTypeckRes`: Allows both `LateContext` and `TypeckResults` to be
used for type-dependent lookup. The implementation here will avoid ICEs
by returning `None` when debug assertions are disabled. With assertions
this will assert that we don't silently lookup anything from a different
body than the current one and that a definition actually exists.
* `HasHirId`: Simply a convenience to allow not typing `.hir_id` at call
sites.
* `MaybeQPath`: This is the old `MaybePath`. Extension functions for
type-dependent path lookups exist here. A lot of these functions aren't
used in the current PR, but what they accomplish is done in various
places I haven't cleaned up yet.
* `MaybeResPath`: Like `MaybeQPath`, but only does non-type-dependent
lookup (`QPath::Resolved`).
* `MaybeDef`: Extension functions for identifying the current definition
and accessing properties. Implemented for several types for convenience.

`MaybeDef` is implemented for `Option` to allow chaining methods
together. e.g.
`cx.ty_based_def(e).opt_parent(cx).opt_impl_ty(cx).is_diag_item(..)`
would chaining `and_then` or `if let` on every step. `MaybeQPath` and
`MaybeResPath` are also implemented for `Option` for the same reason.

`ty_based_def` is just a shorter name for `type_dependent_def`. I'm not
really attached to it, but it's nice that it's a little shorter.

changelog: none
This commit is contained in:
Samuel Tardieu 2025-10-11 07:03:12 +00:00 committed by GitHub
commit ebbbbebf2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
282 changed files with 2051 additions and 1324 deletions

View file

@ -759,8 +759,7 @@ for some users. Adding a configuration is done in the following steps:
Here are some pointers to things you are likely going to need for every lint:
* [Clippy utils][utils] - Various helper functions. Maybe the function you need
is already in here ([`is_type_diagnostic_item`], [`implements_trait`],
[`snippet`], etc)
is already in here ([`implements_trait`], [`snippet`], etc)
* [Clippy diagnostics][diagnostics]
* [Let chains][let-chains]
* [`from_expansion`][from_expansion] and
@ -790,7 +789,6 @@ get away with copying things from existing similar lints. If you are stuck,
don't hesitate to ask on [Zulip] or in the issue/PR.
[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.html
[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html
[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html
[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html
[let-chains]: https://github.com/rust-lang/rust/pull/94927

View file

@ -85,8 +85,8 @@ to check for. All of these methods only check for the base type, generic
arguments have to be checked separately.
```rust
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::paths;
use clippy_utils::res::MaybeDef;
use rustc_span::symbol::sym;
use rustc_hir::LangItem;
@ -97,12 +97,12 @@ impl LateLintPass<'_> for MyStructLint {
// 1. Using diagnostic items
// The last argument is the diagnostic item to check for
if is_type_diagnostic_item(cx, ty, sym::Option) {
if ty.is_diag_item(cx, sym::Option) {
// The type is an `Option`
}
// 2. Using lang items
if is_type_lang_item(cx, ty, LangItem::RangeFull) {
if ty.is_lang_item(cx, LangItem::RangeFull) {
// The type is a full range like `.drain(..)`
}
@ -124,26 +124,28 @@ diagnostic item, lang item or neither.
```rust
use clippy_utils::ty::implements_trait;
use clippy_utils::is_trait_method;
use rustc_span::symbol::sym;
impl LateLintPass<'_> for MyStructLint {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
// 1. Using diagnostic items with the expression
// we use `is_trait_method` function from Clippy's utils
if is_trait_method(cx, expr, sym::Iterator) {
// method call in `expr` belongs to `Iterator` trait
// 1. Get the `DefId` of the trait.
// via lang items
let trait_id = cx.tcx.lang_items().drop_trait();
// via diagnostic items
let trait_id = cx.tcx.get_diagnostic_item(sym::Eq);
// 2. Check for the trait implementation via the `implements_trait` util.
let ty = cx.typeck_results().expr_ty(expr);
if trait_id.is_some_and(|id| implements_trait(cx, ty, id, &[])) {
// `ty` implements the trait.
}
// 2. Using lang items with the expression type
let ty = cx.typeck_results().expr_ty(expr);
if cx.tcx.lang_items()
// we are looking for the `DefId` of `Drop` trait in lang items
.drop_trait()
// then we use it with our type `ty` by calling `implements_trait` from Clippy's utils
.is_some_and(|id| implements_trait(cx, ty, id, &[])) {
// `expr` implements `Drop` trait
}
// 3. If the trait requires additional generic arguments
let trait_id = cx.tcx.lang_items().eq_trait();
if trait_id.is_some_and(|id| implements_trait(cx, ty, id, &[ty])) {
// `ty` implements `PartialEq<Self>`
}
}
}
```
@ -173,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
// We can also check it has a parameter `self`
&& signature.decl.implicit_self.has_implicit_self()
// We can go further and even check if its return type is `String`
&& is_type_lang_item(cx, return_ty(cx, impl_item.hir_id), LangItem::String)
&& return_ty(cx, impl_item.hir_id).is_lang_item(cx, LangItem::String)
{
// ...
}

View file

@ -16,7 +16,7 @@ the [`ExprKind`] that we can access from `expr.kind`:
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_span::sym;
use clippy_utils::is_trait_method;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
@ -28,7 +28,7 @@ impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
// (It's necessary if we want to check that method is specifically belonging to a specific trait,
// for example, a `map` method could belong to user-defined trait instead of to `Iterator`)
// See the next section for more information.
&& is_trait_method(cx, self_arg, sym::OurFancyTrait)
&& cx.ty_based_def(self_arg).opt_parent(cx).is_diag_item(cx, sym::OurFancyTrait)
{
println!("`expr` is a method call for `our_fancy_method`");
}
@ -56,7 +56,7 @@ Let us take a look at how we might check for the implementation of
`our_fancy_method` on a type:
```rust
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use clippy_utils::return_ty;
use rustc_hir::{ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
// We can also check it has a parameter `self`
&& signature.decl.implicit_self.has_implicit_self()
// We can go even further and even check if its return type is `String`
&& is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym::String)
&& return_ty(cx, impl_item.hir_id).is_diag_item(cx, sym::String)
{
println!("`our_fancy_method` is implemented!");
}

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::implements_trait;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@ -46,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
&& let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind
&& func_name.ident.name == sym::new
&& !expr.span.from_expansion()
&& is_type_diagnostic_item(cx, cx.typeck_results().node_type(func_ty.hir_id), sym::Arc)
&& cx.typeck_results().node_type(func_ty.hir_id).is_diag_item(cx, sym::Arc)
&& let arg_ty = cx.typeck_results().expr_ty(arg)
// make sure that the type is not and does not contain any type parameters
&& arg_ty.walk().all(|arg| {

View file

@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node};
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
use clippy_utils::sym;
use clippy_utils::ty::{has_debug_impl, is_copy};
use clippy_utils::usage::local_used_after_expr;
use clippy_utils::{path_res, sym};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Expr, ExprKind, Node};
@ -55,13 +56,13 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
&& let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind
&& let result_type_with_refs = cx.typeck_results().expr_ty(recv)
&& let result_type = result_type_with_refs.peel_refs()
&& is_type_diagnostic_item(cx, result_type, sym::Result)
&& result_type.is_diag_item(cx, sym::Result)
&& let ty::Adt(_, args) = result_type.kind()
{
if !is_copy(cx, result_type) {
if result_type_with_refs != result_type {
return;
} else if let Res::Local(binding_id) = path_res(cx, recv)
} else if let Res::Local(binding_id) = *recv.basic_res()
&& local_used_after_expr(cx, binding_id, recv)
{
return;

View file

@ -2,8 +2,9 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::sugg::Sugg;
use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local, sym};
use clippy_utils::{is_in_test, last_path_segment, local_is_initialized, sym};
use rustc_errors::Applicability;
use rustc_hir::{self as hir, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -68,15 +69,15 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Assign(lhs, rhs, _) = e.kind
&& let typeck = cx.typeck_results()
&& let (call_kind, fn_name, fn_id, fn_arg, fn_gen_args) = match rhs.kind {
&& let (call_kind, fn_name, fn_def, fn_arg, fn_gen_args) = match rhs.kind {
ExprKind::Call(f, [arg])
if let ExprKind::Path(fn_path) = &f.kind
&& let Some(id) = typeck.qpath_res(fn_path, f.hir_id).opt_def_id() =>
&& let Some(def) = typeck.qpath_res(fn_path, f.hir_id).opt_def(cx) =>
{
(CallKind::Ufcs, last_path_segment(fn_path).ident.name, id, arg, typeck.node_args(f.hir_id))
(CallKind::Ufcs, last_path_segment(fn_path).ident.name, def, arg, typeck.node_args(f.hir_id))
},
ExprKind::MethodCall(name, recv, [], _) if let Some(id) = typeck.type_dependent_def_id(rhs.hir_id) => {
(CallKind::Method, name.ident.name, id, recv, typeck.node_args(rhs.hir_id))
ExprKind::MethodCall(name, recv, [], _) if let Some(def) = typeck.type_dependent_def(rhs.hir_id) => {
(CallKind::Method, name.ident.name, def, recv, typeck.node_args(rhs.hir_id))
},
_ => return,
}
@ -84,20 +85,20 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
// Don't lint in macros.
&& ctxt.is_root()
&& let which_trait = match fn_name {
sym::clone if is_diag_trait_item(cx, fn_id, sym::Clone) => CloneTrait::Clone,
sym::clone if fn_def.assoc_fn_parent(cx).is_diag_item(cx, sym::Clone) => CloneTrait::Clone,
sym::to_owned
if is_diag_trait_item(cx, fn_id, sym::ToOwned)
if fn_def.assoc_fn_parent(cx).is_diag_item(cx, sym::ToOwned)
&& self.msrv.meets(cx, msrvs::CLONE_INTO) =>
{
CloneTrait::ToOwned
},
_ => return,
}
&& let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args)
&& let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_def.1, fn_gen_args)
// TODO: This check currently bails if the local variable has no initializer.
// That is overly conservative - the lint should fire even if there was no initializer,
// but the variable has been initialized before `lhs` was evaluated.
&& path_to_local(lhs).is_none_or(|lhs| local_is_initialized(cx, lhs))
&& lhs.res_local_id().is_none_or(|lhs| local_is_initialized(cx, lhs))
&& let Some(resolved_impl) = cx.tcx.impl_of_assoc(resolved_fn.def_id())
// Derived forms don't implement `clone_from`/`clone_into`.
// See https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305

View file

@ -2,9 +2,10 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::higher::has_let_expr;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::ty::implements_trait;
use clippy_utils::{eq_expr_value, sym};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@ -431,9 +432,7 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Optio
},
ExprKind::MethodCall(path, receiver, args, _) => {
let type_of_receiver = cx.typeck_results().expr_ty(receiver);
if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option)
&& !is_type_diagnostic_item(cx, type_of_receiver, sym::Result)
{
if !type_of_receiver.is_diag_item(cx, sym::Option) && !type_of_receiver.is_diag_item(cx, sym::Result) {
return None;
}
METHODS_WITH_NEGATION

View file

@ -1,11 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_default_equivalent;
use clippy_utils::macros::macro_backtrace;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::ty::expr_sig;
use clippy_utils::{is_default_equivalent, path_def_id};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind};
use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LangItem, LetStmt, Node, QPath, Ty, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::declare_lint_pass;
use rustc_span::{Span, sym};
@ -44,7 +45,7 @@ impl LateLintPass<'_> for BoxDefault {
// And that method is `new`
&& seg.ident.name == sym::new
// And the call is that of a `Box` method
&& path_def_id(cx, ty).is_some_and(|id| Some(id) == cx.tcx.lang_items().owned_box())
&& ty.basic_res().is_lang_item(cx, LangItem::OwnedBox)
// And the single argument to the call is another function call
// This is the `T::default()` (or default equivalent) of `Box::new(T::default())`
&& let ExprKind::Call(arg_path, _) = arg.kind

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{expr_or_init, is_path_diagnostic_item, std_or_core, sym};
use clippy_utils::{expr_or_init, std_or_core, sym};
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind};
@ -53,7 +54,7 @@ fn is_expr_const_aligned(cx: &LateContext<'_>, expr: &Expr<'_>, to: &Ty<'_>) ->
fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool {
if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind
&& is_path_diagnostic_item(cx, fun, sym::mem_align_of)
&& fun.basic_res().is_diag_item(cx, sym::mem_align_of)
&& let Some(args) = path.segments.last().and_then(|seg| seg.args)
&& let [GenericArg::Type(generic_ty)] = args.args
{

View file

@ -1,8 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::{SpanRangeExt, snippet_opt};
use clippy_utils::visitors::{Visitable, for_each_expr_without_closures};
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias};
use rustc_ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -167,11 +168,11 @@ pub(super) fn check<'tcx>(
sym::assert_ne_macro,
sym::debug_assert_ne_macro,
];
matches!(expr.span.ctxt().outer_expn_data().macro_def_id, Some(def_id) if
matches!(expr.span.ctxt().outer_expn_data().macro_def_id, Some(def_id) if
cx.tcx.get_diagnostic_name(def_id).is_some_and(|sym| ALLOWED_MACROS.contains(&sym)))
}
if let Some(id) = path_to_local(cast_expr)
if let Some(id) = cast_expr.res_local_id()
&& !cx.tcx.hir_span(id).eq_ctxt(cast_expr.span)
{
// Binding context is different than the identifiers context.

View file

@ -1,9 +1,10 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::sugg::Sugg;
use clippy_utils::visitors::is_const_evaluatable;
use clippy_utils::{is_in_const_context, is_mutable, is_trait_method};
use clippy_utils::{is_in_const_context, is_mutable};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -73,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ClonedRefToSliceRefs<'_> {
// check for clones
&& let ExprKind::MethodCall(_, val, _, _) = item.kind
&& is_trait_method(cx, item, sym::Clone)
&& cx.ty_based_def(item).opt_parent(cx).is_diag_item(cx, sym::Clone)
// check for immutability or purity
&& (!is_mutable(cx, val) || is_const_evaluatable(cx, val))

View file

@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::{IntoSpan, SpanRangeExt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{LimitStack, get_async_fn_body, sym};
use core::ops::ControlFlow;
@ -93,7 +93,7 @@ impl CognitiveComplexity {
});
let ret_ty = cx.typeck_results().node_type(expr.hir_id);
let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::Result) {
let ret_adjust = if ret_ty.is_diag_item(cx, sym::Result) {
returns
} else {
#[expect(clippy::integer_division)]

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
use clippy_utils::get_enclosing_block;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::visitors::{Visitable, for_each_expr};
use clippy_utils::{get_enclosing_block, path_to_local_id};
use core::ops::ControlFlow;
use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
use rustc_lint::{LateContext, LateLintPass};
@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
let ty = cx.typeck_results().pat_ty(local.pat);
matches!(
get_type_diagnostic_name(cx, ty),
ty.opt_diag_name(cx),
Some(
sym::BTreeMap
| sym::BTreeSet
@ -71,7 +71,7 @@ fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
| sym::Vec
| sym::VecDeque
)
) || is_type_lang_item(cx, ty, LangItem::String)
) || ty.is_lang_item(cx, LangItem::String)
}
fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool {
@ -81,7 +81,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI
// Inspect all expressions and sub-expressions in the block.
for_each_expr(cx, block, |expr| {
// Ignore expressions that are not simply `id`.
if !path_to_local_id(expr, id) {
if expr.res_local_id() != Some(id) {
return ControlFlow::Continue(());
}
@ -93,7 +93,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI
// id = ...; // Not reading `id`.
if let Node::Expr(parent) = cx.tcx.parent_hir_node(expr.hir_id)
&& let ExprKind::Assign(lhs, ..) = parent.kind
&& path_to_local_id(lhs, id)
&& lhs.res_local_id() == Some(id)
{
return ControlFlow::Continue(());
}
@ -107,7 +107,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI
// have side effects, so consider them a read.
if let Node::Expr(parent) = cx.tcx.parent_hir_node(expr.hir_id)
&& let ExprKind::MethodCall(_, receiver, args, _) = parent.kind
&& path_to_local_id(receiver, id)
&& receiver.res_local_id() == Some(id)
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
&& !method_def_id.is_local()
{

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
use clippy_utils::ty::{adjust_derefs_manually_drop, implements_trait, is_manually_drop, peel_and_count_ty_refs};
use clippy_utils::{
DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_from_proc_macro, is_lint_allowed,
path_to_local,
};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxIndexMap;
@ -239,7 +239,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
return;
}
if let Some(local) = path_to_local(expr) {
if let Some(local) = expr.res_local_id() {
self.check_local_usage(cx, expr, local);
}

View file

@ -1,4 +1,4 @@
use clippy_utils::path_res;
use clippy_utils::res::MaybeResPath;
use rustc_hir::def::Res;
use rustc_hir::{Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
self_ty,
..
}) = item.kind
&& let Res::Def(_, def_id) = path_res(cx, self_ty)
&& let Res::Def(_, def_id) = *self_ty.basic_res()
&& let Some(local_def_id) = def_id.as_local()
{
let adt_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id);

View file

@ -1,7 +1,8 @@
use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC};
use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::implements_trait_with_env;
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{fulfill_or_allowed, is_doc_hidden, is_inside_always_const_context, method_chain_args, return_ty};
use rustc_hir::{BodyId, FnSig, OwnerId, Safety};
@ -62,7 +63,7 @@ pub fn check(
);
}
if !headers.errors {
if is_type_diagnostic_item(cx, return_ty(cx, owner_id), sym::Result) {
if return_ty(cx, owner_id).is_diag_item(cx, sym::Result) {
span_lint(
cx,
MISSING_ERRORS_DOC,
@ -83,7 +84,7 @@ pub fn check(
&[],
)
&& let ty::Coroutine(_, subs) = ret_ty.kind()
&& is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result)
&& subs.as_coroutine().return_ty().is_diag_item(cx, sym::Result)
{
span_lint(
cx,
@ -119,10 +120,7 @@ fn find_panic(cx: &LateContext<'_>, body_id: BodyId) -> Option<Span> {
if let Some(arglists) =
method_chain_args(expr, &[sym::unwrap]).or_else(|| method_chain_args(expr, &[sym::expect]))
&& let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs()
&& matches!(
get_type_diagnostic_name(cx, receiver_ty),
Some(sym::Option | sym::Result)
)
&& matches!(receiver_ty.opt_diag_name(cx), Some(sym::Option | sym::Result))
&& !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id])
&& panic_span.is_none()
{

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_must_use_func_call;
use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::{is_copy, is_must_use_ty};
use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@ -97,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
sym::mem_forget if arg_ty.is_ref() => return,
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
sym::mem_forget if is_copy => return,
sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return,
sym::mem_drop if arg_ty.is_lang_item(cx, LangItem::ManuallyDrop) => return,
sym::mem_drop
if !(arg_ty.needs_drop(cx.tcx, cx.typing_env())
|| is_must_use_func_call(cx, arg)

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::{span_lint, span_lint_hir_and_then};
use clippy_utils::path_res;
use clippy_utils::res::MaybeResPath;
use clippy_utils::ty::implements_trait;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{Item, ItemKind};
@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_ref.trait_def_id())
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
&& error_def_id == trait_def_id
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
&& let Some(def_id) = imp.self_ty.basic_res().opt_def_id().and_then(DefId::as_local)
&& let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
&& ident.name == sym::Error
&& is_visible_outside_module(cx, def_id) =>

View file

@ -1,11 +1,9 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::higher::VecArgs;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
use clippy_utils::ty::get_type_diagnostic_name;
use clippy_utils::usage::{local_used_after_expr, local_used_in};
use clippy_utils::{
get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
};
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate};
use rustc_abi::ExternAbi;
use rustc_errors::Applicability;
use rustc_hir::attrs::AttributeKind;
@ -144,7 +142,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
{
let callee_ty_raw = typeck.expr_ty(callee);
let callee_ty = callee_ty_raw.peel_refs();
if matches!(get_type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
if matches!(callee_ty.opt_diag_name(cx), Some(sym::Arc | sym::Rc))
|| !check_inputs(typeck, body.params, None, args)
{
return;
@ -218,7 +216,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
"redundant closure",
|diag| {
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
if path_to_local(callee).is_some_and(|l| {
if callee.res_local_id().is_some_and(|l| {
// FIXME: Do we really need this `local_used_in` check?
// Isn't it checking something like... `callee(callee)`?
// If somehow this check is needed, add some test for it,
@ -307,7 +305,7 @@ fn check_inputs(
matches!(
p.pat.kind,
PatKind::Binding(BindingMode::NONE, id, _, None)
if path_to_local_id(arg, id)
if arg.res_local_id() == Some(id)
)
// Only allow adjustments which change regions (i.e. re-borrowing).
&& typeck

View file

@ -1,7 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_expn_of, path_def_id, sym};
use clippy_utils::{is_expn_of, sym};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
@ -59,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
&& let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind)
&& let ExprKind::Call(write_recv_path, []) = write_recv.kind
&& write_fun.ident.name == sym::write_fmt
&& let Some(def_id) = path_def_id(cx, write_recv_path)
&& let Some(def_id) = write_recv_path.basic_res().opt_def_id()
{
// match calls to std::io::stdout() / std::io::stderr ()
let (dest_name, prefix) = match cx.tcx.get_diagnostic_name(def_id) {

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
use clippy_utils::method_chain_args;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@ -84,9 +84,7 @@ fn lint_impl_body(cx: &LateContext<'_>, item_def_id: hir::OwnerId, impl_span: Sp
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &[sym::unwrap]) {
let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
|| is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
{
if receiver_ty.is_diag_item(self.lcx, sym::Option) || receiver_ty.is_diag_item(self.lcx, sym::Result) {
self.result.push(expr.span);
}
}

View file

@ -1,9 +1,10 @@
use clippy_utils::consts::Constant::{F32, F64, Int};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::{
eq_expr_value, get_parent_expr, has_ambiguous_literal_in_expr, higher, is_in_const_context,
is_inherent_method_call, is_no_std_crate, numeric_literal, peel_blocks, sugg, sym,
eq_expr_value, get_parent_expr, has_ambiguous_literal_in_expr, higher, is_in_const_context, is_no_std_crate,
numeric_literal, peel_blocks, sugg, sym,
};
use rustc_ast::ast;
use rustc_errors::Applicability;
@ -737,7 +738,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind {
let recv_ty = cx.typeck_results().expr_ty(receiver);
if recv_ty.is_floating_point() && !is_no_std_crate(cx) && is_inherent_method_call(cx, expr) {
if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) {
match path.ident.name {
sym::ln => check_ln1p(cx, expr, receiver),
sym::log => check_log_base(cx, expr, receiver, args),

View file

@ -9,9 +9,10 @@ use clippy_utils::macros::{
root_macro_call_first_node,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::{SpanRangeExt, snippet};
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use clippy_utils::{is_diag_trait_item, is_from_proc_macro, is_in_test, trait_ref_of_method};
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_from_proc_macro, is_in_test, trait_ref_of_method};
use itertools::Itertools;
use rustc_ast::{
FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
@ -344,7 +345,7 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> {
if let Some(placeholder_span) = placeholder.span
&& *options != FormatOptions::default()
&& let ty = self.cx.typeck_results().expr_ty(arg).peel_refs()
&& is_type_lang_item(self.cx, ty, LangItem::FormatArguments)
&& ty.is_lang_item(self.cx, LangItem::FormatArguments)
{
span_lint_and_then(
self.cx,
@ -497,8 +498,11 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> {
let cx = self.cx;
if !value.span.from_expansion()
&& let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
&& is_diag_trait_item(cx, method_def_id, sym::ToString)
&& cx
.typeck_results()
.type_dependent_def_id(value.hir_id)
.opt_parent(cx)
.is_diag_item(cx, sym::ToString)
&& let receiver_ty = cx.typeck_results().expr_ty(receiver)
&& let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display)
&& let (n_needed_derefs, target) =

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators, sym};
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::{get_parent_as_impl, peel_ref_operators, sym};
use rustc_ast::{FormatArgsPiece, FormatTrait};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
@ -157,8 +158,12 @@ impl FormatImplExpr<'_, '_> {
&& path.ident.name == sym::to_string
// Is the method a part of the ToString trait? (i.e. not to_string() implemented
// separately)
&& let Some(expr_def_id) = self.cx.typeck_results().type_dependent_def_id(self.expr.hir_id)
&& is_diag_trait_item(self.cx, expr_def_id, sym::ToString)
&& self
.cx
.typeck_results()
.type_dependent_def_id(self.expr.hir_id)
.opt_parent(self.cx)
.is_diag_item(self.cx, sym::ToString)
// Is the method is called on self
&& let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind
&& let [segment] = path.segments
@ -210,7 +215,7 @@ impl FormatImplExpr<'_, '_> {
// Since the argument to fmt is itself a reference: &self
let reference = peel_ref_operators(self.cx, arg);
// Is the reference self?
if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
if reference.res_local_id().map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
let FormatTraitNames { name, .. } = self.format_trait_impl;
span_lint(
self.cx,

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::res::MaybeDef;
use rustc_hir::{AssignOpKind, Expr, ExprKind, LangItem, MatchSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@ -41,7 +41,10 @@ declare_clippy_lint! {
declare_lint_pass!(FormatPushString => [FORMAT_PUSH_STRING]);
fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String)
cx.typeck_results()
.expr_ty(e)
.peel_refs()
.is_lang_item(cx, LangItem::String)
}
fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
let e = e.peel_blocks().peel_borrows();

View file

@ -4,7 +4,7 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::path_def_id;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::SpanRangeExt;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{Visitor, walk_path};
@ -90,7 +90,12 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
|diag| {
// If the target type is likely foreign mention the orphan rules as it's a common source of
// confusion
if path_def_id(cx, target_ty.peel_refs()).is_none_or(|id| !id.is_local()) {
if target_ty
.peel_refs()
.basic_res()
.opt_def_id()
.is_none_or(|id| !id.is_local())
{
diag.help(
"`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\
https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence"

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::res::MaybeResPath;
use clippy_utils::sym;
use clippy_utils::ty::is_c_void;
use clippy_utils::{path_def_id, sym};
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
@ -41,7 +42,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
if let ExprKind::Call(box_from_raw, [arg]) = expr.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind
&& seg.ident.name == sym::from_raw
&& let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
&& let Some(type_str) = ty.basic_res().opt_def_id().and_then(|id| def_id_matches_type(cx, id))
&& let arg_kind = cx.typeck_results().expr_ty(arg).kind()
&& let ty::RawPtr(ty, _) = arg_kind
&& is_c_void(cx, *ty)

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{is_in_const_context, is_integer_literal, sym};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, PrimTy, QPath, TyKind, def};
@ -89,5 +89,5 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
/// Checks if a Ty is `String` or `&str`
fn is_ty_stringish(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
is_type_lang_item(cx, ty, LangItem::String) || ty.peel_refs().is_str()
ty.is_lang_item(cx, LangItem::String) || ty.peel_refs().is_str()
}

View file

@ -1,12 +1,13 @@
use clippy_utils::res::MaybeResPath;
use rustc_hir::{self as hir, HirId, HirIdSet, intravisit};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::def_id::LocalDefId;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::iter_input_pats;
use clippy_utils::ty::is_unsafe_fn;
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{iter_input_pats, path_to_local};
use core::ops::ControlFlow;
@ -87,7 +88,7 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
}
fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
if path_to_local(arg).is_some_and(|id| raw_ptrs.contains(&id)) {
if arg.res_local_id().is_some_and(|id| raw_ptrs.contains(&id)) {
span_lint(
cx,
NOT_UNSAFE_PTR_ARG_DEREF,

View file

@ -1,4 +1,5 @@
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use rustc_errors::Diag;
use rustc_hir as hir;
use rustc_lint::{LateContext, LintContext};
@ -6,7 +7,7 @@ use rustc_middle::ty::{self, Ty};
use rustc_span::{Span, sym};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
use clippy_utils::ty::{AdtVariantInfo, approx_ty_size};
use clippy_utils::{is_no_std_crate, trait_ref_of_method};
use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
@ -24,7 +25,7 @@ fn result_err_ty<'tcx>(
&& let ty = cx
.tcx
.instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
&& is_type_diagnostic_item(cx, ty, sym::Result)
&& ty.is_diag_item(cx, sym::Result)
&& let ty::Adt(_, args) = ty.kind()
{
let err_ty = args.type_at(1);

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{eq_expr_value, higher, sym};
use core::ops::ControlFlow;
@ -95,7 +95,7 @@ fn mutex_lock_call<'tcx>(
if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind
&& path.ident.name == sym::lock
&& let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
&& is_type_diagnostic_item(cx, ty, sym::Mutex)
&& ty.is_diag_item(cx, sym::Mutex)
&& op_mutex.is_none_or(|op| eq_expr_value(cx, self_arg, op))
{
ControlFlow::Break(self_arg)

View file

@ -2,11 +2,11 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::{
contains_return, expr_adjustment_requires_coercion, higher, is_else_clause, is_in_const_context, is_res_lang_ctor,
path_res, peel_blocks, sym,
contains_return, expr_adjustment_requires_coercion, higher, is_else_clause, is_in_const_context, peel_blocks, sym,
};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
@ -73,8 +73,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
&& !expr.span.from_expansion()
&& !then_expr.span.from_expansion()
&& is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
&& then_call.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
&& peel_blocks(els).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
&& !is_else_clause(cx.tcx, expr)
&& !is_in_const_context(cx)
&& self.msrv.meets(cx, msrvs::BOOL_THEN)

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::{IntoSpan, SpanRangeExt, first_line_of_span, indent_of, reindent_multiline, snippet};
use clippy_utils::ty::needs_ordered_drop;
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{
ContainsName, HirEqInterExpr, SpanlessEq, capture_local_usage, get_enclosing_block, hash_expr, hash_stmt,
path_to_local,
};
use core::iter;
use core::ops::ControlFlow;
@ -149,7 +149,7 @@ fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool {
/// Checks if the statement modifies or moves any of the given locals.
fn modifies_any_local<'tcx>(cx: &LateContext<'tcx>, s: &'tcx Stmt<'_>, locals: &HirIdSet) -> bool {
for_each_expr_without_closures(s, |e| {
if let Some(id) = path_to_local(e)
if let Some(id) = e.res_local_id()
&& locals.contains(&id)
&& !capture_local_usage(cx, e).is_imm_ref()
{
@ -198,7 +198,7 @@ fn scan_block_for_eq<'tcx>(
let mut cond_locals = HirIdSet::default();
for &cond in conds {
let _: Option<!> = for_each_expr_without_closures(cond, |e| {
if let Some(id) = path_to_local(e) {
if let Some(id) = e.res_local_id() {
cond_locals.insert(id);
}
ControlFlow::Continue(())

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::res::MaybeResPath;
use clippy_utils::ty::InteriorMut;
use clippy_utils::{SpanlessEq, eq_expr_value, find_binding_init, hash_expr, path_to_local, search_same};
use clippy_utils::{SpanlessEq, eq_expr_value, find_binding_init, hash_expr, search_same};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
@ -16,7 +17,7 @@ fn method_caller_is_mutable<'tcx>(
interior_mut.is_interior_mut_ty(cx, caller_ty)
|| caller_ty.is_mutable_ptr()
// `find_binding_init` will return the binding iff its not mutable
|| path_to_local(caller_expr)
|| caller_expr.res_local_id()
.and_then(|hid| find_binding_init(cx, hid))
.is_none()
}

View file

@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
use clippy_utils::res::MaybeDef;
use rustc_errors::{Applicability, Diag};
use rustc_hir::intravisit::{Visitor, VisitorExt, walk_body, walk_expr, walk_ty};
use rustc_hir::{self as hir, AmbigArg, Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
@ -14,7 +15,6 @@ use rustc_span::Span;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
use clippy_utils::sym;
use clippy_utils::ty::is_type_diagnostic_item;
declare_clippy_lint! {
/// ### What it does
@ -227,14 +227,14 @@ impl<'tcx> ImplicitHasherType<'tcx> {
let ty = lower_ty(cx.tcx, hir_ty);
if is_type_diagnostic_item(cx, ty, sym::HashMap) && params_len == 2 {
if ty.is_diag_item(cx, sym::HashMap) && params_len == 2 {
Some(ImplicitHasherType::HashMap(
hir_ty.span,
ty,
snippet(cx, params[0].span, "K"),
snippet(cx, params[1].span, "V"),
))
} else if is_type_diagnostic_item(cx, ty, sym::HashSet) && params_len == 1 {
} else if ty.is_diag_item(cx, sym::HashSet) && params_len == 1 {
Some(ImplicitHasherType::HashSet(
hir_ty.span,
ty,

View file

@ -2,9 +2,10 @@ use clippy_config::Conf;
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::is_lint_allowed;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::ty::is_copy;
use clippy_utils::{is_lint_allowed, path_to_local};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -225,7 +226,7 @@ impl<'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'_, 'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let Some(local_id) = path_to_local(expr) {
if let Some(local_id) = expr.res_local_id() {
let Self {
cx,
ref mut slice_lint_info,

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{peel_blocks, peel_hir_expr_while, sym};
use rustc_ast::LitKind;
use rustc_errors::Applicability;
@ -47,7 +47,11 @@ impl<'tcx> LateLintPass<'tcx> for IneffectiveOpenOptions {
if let ExprKind::MethodCall(name, recv, [_], _) = expr.kind
&& name.ident.name == sym::open
&& !expr.span.from_expansion()
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::FsOpenOptions)
&& cx
.typeck_results()
.expr_ty(recv)
.peel_refs()
.is_diag_item(cx, sym::FsOpenOptions)
{
let mut append = false;
let mut write = None;

View file

@ -1,5 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::implements_trait;
use clippy_utils::{higher, sym};
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -235,7 +236,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
} else if method.ident.name == sym::collect {
let ty = cx.typeck_results().expr_ty(expr);
if matches!(
get_type_diagnostic_name(cx, ty),
ty.opt_diag_name(cx),
Some(
sym::BinaryHeap
| sym::BTreeMap

View file

@ -1,5 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::implements_trait;
use clippy_utils::{return_ty, trait_ref_of_method};
use rustc_abi::ExternAbi;
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem};
@ -104,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
&& impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
&& !impl_item.span.from_expansion()
// Check if return type is String
&& is_type_lang_item(cx, return_ty(cx, impl_item.owner_id), LangItem::String)
&& return_ty(cx, impl_item.owner_id).is_lang_item(cx, LangItem::String)
// Filters instances of to_string which are required by a trait
&& trait_ref_of_method(cx, impl_item.owner_id).is_none()
{

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::higher::ForLoop;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::sym;
@ -55,9 +55,7 @@ impl LateLintPass<'_> for IterOverHashType {
if let Some(for_loop) = ForLoop::hir(expr)
&& !for_loop.body.span.from_expansion()
&& let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
&& hash_iter_tys
.into_iter()
.any(|sym| is_type_diagnostic_item(cx, ty, sym))
&& hash_iter_tys.into_iter().any(|sym| ty.is_diag_item(cx, sym))
{
span_lint(
cx,

View file

@ -1,10 +1,9 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::source::{SpanRangeExt, snippet_with_context};
use clippy_utils::sugg::{Sugg, has_enclosing_paren};
use clippy_utils::ty::implements_trait;
use clippy_utils::{
fulfill_or_allowed, get_parent_as_impl, is_trait_method, parent_item_name, peel_ref_operators, sym,
};
use clippy_utils::{fulfill_or_allowed, get_parent_as_impl, parent_item_name, peel_ref_operators, sym};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@ -204,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
}
if let ExprKind::MethodCall(method, lhs_expr, [rhs_expr], _) = expr.kind
&& is_trait_method(cx, expr, sym::PartialEq)
&& cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::PartialEq)
&& !expr.span.from_expansion()
{
check_empty_expr(

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::path_to_local_id;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
use rustc_errors::Applicability;
@ -145,7 +145,7 @@ fn check_assign<'tcx>(
&& let Some(expr) = block.stmts.iter().last()
&& let hir::StmtKind::Semi(expr) = expr.kind
&& let hir::ExprKind::Assign(var, value, _) = expr.kind
&& path_to_local_id(var, decl)
&& var.res_local_id() == Some(decl)
{
if block
.stmts

View file

@ -1,8 +1,8 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_diag_item_method, is_trait_method, path_to_local_id, sym};
use clippy_utils::res::{MaybeDef, MaybeResPath, MaybeTypeckRes};
use clippy_utils::sym;
use rustc_errors::Applicability;
use rustc_hir::{Body, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -73,10 +73,13 @@ impl_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]);
impl LateLintPass<'_> for LinesFilterMapOk {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::MethodCall(fm_method, fm_receiver, fm_args, fm_span) = expr.kind
&& is_trait_method(cx, expr, sym::Iterator)
&& cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
&& let fm_method_name = fm_method.ident.name
&& matches!(fm_method_name, sym::filter_map | sym::flat_map | sym::flatten)
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines)
&& cx
.typeck_results()
.expr_ty_adjusted(fm_receiver)
.is_diag_item(cx, sym::IoLines)
&& should_lint(cx, fm_args, fm_method_name)
&& self.msrv.meets(cx, msrvs::MAP_WHILE)
{
@ -117,10 +120,15 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_name: Symbol) ->
params: [param], value, ..
} = cx.tcx.hir_body(*body)
&& let ExprKind::MethodCall(method, receiver, [], _) = value.kind
&& path_to_local_id(receiver, param.pat.hir_id)
&& let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id)
{
is_diag_item_method(cx, method_did, sym::Result) && method.ident.name == sym::ok
method.ident.name == sym::ok
&& receiver.res_local_id() == Some(param.pat.hir_id)
&& cx
.typeck_results()
.type_dependent_def_id(value.hir_id)
.opt_parent(cx)
.opt_impl_ty(cx)
.is_diag_item(cx, sym::Result)
} else {
false
}

View file

@ -1,9 +1,9 @@
use std::ops::ControlFlow;
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{eq_expr_value, higher, path_to_local_id, sym};
use clippy_utils::{eq_expr_value, higher, sym};
use rustc_errors::{Applicability, MultiSpan};
use rustc_hir::{Expr, ExprKind, LangItem, Node, Pat, PatKind};
use rustc_lint::LateContext;
@ -49,7 +49,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, iterable: &Expr
{
// Destructured iterator element `(idx, _)`, look for uses of the binding
for_each_expr(cx, body, |expr| {
if path_to_local_id(expr, binding_id) {
if expr.res_local_id() == Some(binding_id) {
check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv);
}
CONTINUE
@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, iterable: &Expr
// Bound as a tuple, look for `tup.0`
for_each_expr(cx, body, |expr| {
if let ExprKind::Field(e, field) = expr.kind
&& path_to_local_id(e, binding_id)
&& e.res_local_id() == Some(binding_id)
&& field.name == sym::integer(0)
{
check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv);
@ -81,7 +81,7 @@ fn check_index_usage<'tcx>(
return;
};
let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String);
let is_string_like = |ty: Ty<'_>| ty.is_str() || ty.is_lang_item(cx, LangItem::String);
let message = match parent_expr.kind {
ExprKind::MethodCall(segment, recv, ..)
// We currently only lint `str` methods (which `String` can deref to), so a `.is_str()` check is sufficient here

View file

@ -1,6 +1,6 @@
use super::EXPLICIT_INTO_ITER_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_trait_method;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::source::snippet_with_context;
use rustc_errors::Applicability;
use rustc_hir::Expr;
@ -43,7 +43,11 @@ impl AdjustKind {
}
pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) {
if !is_trait_method(cx, call_expr, sym::IntoIterator) {
if !cx
.ty_based_def(call_expr)
.opt_parent(cx)
.is_diag_item(cx, sym::IntoIterator)
{
return;
}

View file

@ -1,10 +1,11 @@
use super::EXPLICIT_ITER_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sym;
use clippy_utils::ty::{
implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
implements_trait, implements_trait_with_env, is_copy, make_normalized_projection,
make_normalized_projection_with_regions, normalize_with_regions,
};
use rustc_errors::Applicability;
@ -127,8 +128,7 @@ fn is_ref_iterable<'tcx>(
let self_ty = typeck.expr_ty(self_arg);
let self_is_copy = is_copy(cx, self_ty);
if is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox)
&& !msrv.meets(cx, msrvs::BOX_INTO_ITER)
if self_ty.peel_refs().is_lang_item(cx, rustc_hir::LangItem::OwnedBox) && !msrv.meets(cx, msrvs::BOX_INTO_ITER)
{
return None;
}

View file

@ -1,7 +1,7 @@
use super::FOR_KV_MAP;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{pat_is_wild, sugg};
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
_ => arg,
};
if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) {
if ty.is_diag_item(cx, sym::HashMap) || ty.is_diag_item(cx, sym::BTreeMap) {
span_lint_and_then(
cx,
FOR_KV_MAP,

View file

@ -1,12 +1,12 @@
use super::ITER_NEXT_LOOP;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_trait_method;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_span::sym;
pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) {
if is_trait_method(cx, arg, sym::Iterator) {
if cx.ty_based_def(arg).opt_parent(cx).is_diag_item(cx, sym::Iterator) {
span_lint(
cx,
ITER_NEXT_LOOP,

View file

@ -1,12 +1,12 @@
use super::MANUAL_FIND;
use super::utils::make_iterator_snippet;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::implements_trait;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt};
use clippy_utils::{higher, peel_blocks_with_stmt};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
use rustc_lint::LateContext;
@ -34,8 +34,8 @@ pub(super) fn check<'tcx>(
&& let StmtKind::Semi(semi) = stmt.kind
&& let ExprKind::Ret(Some(ret_value)) = semi.kind
&& let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind
&& is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome)
&& path_res(cx, inner_ret) == Res::Local(binding_id)
&& ctor.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
&& inner_ret.res_local_id() == Some(binding_id)
&& !contains_return_break_continue_macro(cond)
&& let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr)
{
@ -150,7 +150,7 @@ fn last_stmt_and_ret<'tcx>(
&& let Some((_, Node::Block(block))) = parent_iter.next()
&& let Some((last_stmt, last_ret)) = extract(block)
&& last_stmt.hir_id == node_hir
&& is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone)
&& last_ret.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionNone)
&& let Some((_, Node::Expr(_block))) = parent_iter.next()
// This includes the function header
&& let Some((_, func)) = parent_iter.next()

View file

@ -2,9 +2,10 @@ use super::MANUAL_FLATTEN;
use super::utils::make_iterator_snippet;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::{HasSession, indent_of, reindent_multiline, snippet_with_applicability};
use clippy_utils::visitors::is_local_used;
use clippy_utils::{higher, is_refutable, path_to_local_id, peel_blocks_with_stmt, span_contains_comment};
use clippy_utils::{higher, is_refutable, peel_blocks_with_stmt, span_contains_comment};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, Pat, PatKind};
@ -27,7 +28,7 @@ pub(super) fn check<'tcx>(
= higher::IfLet::hir(cx, inner_expr)
// Ensure match_expr in `if let` statement is the same as the pat from the for-loop
&& let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind
&& path_to_local_id(let_expr, pat_hir_id)
&& let_expr.res_local_id() == Some(pat_hir_id)
// Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
&& let PatKind::TupleStruct(ref qpath, [inner_pat], _) = let_pat.kind
&& let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id)

View file

@ -1,10 +1,11 @@
use super::{IncrementVisitor, InitializeVisitor, MANUAL_MEMCPY};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_copy;
use clippy_utils::usage::local_used_in;
use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
use clippy_utils::{get_enclosing_block, higher, sugg};
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_hir::intravisit::walk_block;
@ -67,7 +68,7 @@ pub(super) fn check<'tcx>(
&& !local_used_in(cx, canonical_id, base_left)
&& !local_used_in(cx, canonical_id, base_right)
// Source and destination must be different
&& path_to_local(base_left) != path_to_local(base_right)
&& base_left.res_local_id() != base_right.res_local_id()
{
Some((
ty,
@ -128,7 +129,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
if let ExprKind::MethodCall(method, recv, [], _) = end.kind
&& method.ident.name == sym::len
&& path_to_local(recv) == path_to_local(base)
&& recv.res_local_id() == base.res_local_id()
{
if sugg.to_string() == end_str {
sugg::EMPTY.into()
@ -364,7 +365,7 @@ fn get_details_from_idx<'tcx>(
starts: &[Start<'tcx>],
) -> Option<(StartKind<'tcx>, Offset)> {
fn get_start<'tcx>(e: &Expr<'_>, starts: &[Start<'tcx>]) -> Option<StartKind<'tcx>> {
let id = path_to_local(e)?;
let id = e.res_local_id()?;
starts.iter().find(|start| start.id == id).map(|start| start.kind)
}
@ -425,7 +426,7 @@ fn get_assignments<'a, 'tcx>(
.chain(*expr)
.filter(move |e| {
if let ExprKind::AssignOp(_, place, _) = e.kind {
path_to_local(place).is_some_and(|id| {
place.res_local_id().is_some_and(|id| {
!loop_counters
.iter()
// skip the first item which should be `StartKind::Range`

View file

@ -1,7 +1,7 @@
use super::MISSING_SPIN_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::std_or_core;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::Applicability;
use rustc_hir::{Block, Expr, ExprKind};
use rustc_lint::LateContext;
@ -40,7 +40,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'
&& let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind
&& [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name)
&& let callee_ty = cx.typeck_results().expr_ty(callee)
&& is_type_diagnostic_item(cx, callee_ty, sym::AtomicBool)
&& callee_ty.is_diag_item(cx, sym::AtomicBool)
&& let Some(std_or_core) = std_or_core(cx)
{
span_lint_and_sugg(

View file

@ -1,6 +1,7 @@
use super::MUT_RANGE_BOUND;
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::{get_enclosing_block, higher, path_to_local};
use clippy_utils::res::MaybeResPath;
use clippy_utils::{get_enclosing_block, higher};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Node, PatKind};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@ -39,7 +40,7 @@ fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) {
}
fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId> {
if let Some(hir_id) = path_to_local(bound)
if let Some(hir_id) = bound.res_local_id()
&& let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
&& let PatKind::Binding(BindingMode::MUT, ..) = pat.kind
{

View file

@ -1,9 +1,10 @@
use super::SAME_ITEM_PUSH;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::Msrv;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{msrvs, path_to_local, std_or_core, sym};
use clippy_utils::ty::implements_trait;
use clippy_utils::{msrvs, std_or_core, sym};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -125,7 +126,7 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
if !self.non_deterministic_expr
&& !self.multiple_pushes
&& let Some((vec, _, _)) = self.vec_push
&& let Some(hir_id) = path_to_local(vec)
&& let Some(hir_id) = vec.res_local_id()
{
!self.used_locals.contains(&hir_id)
} else {
@ -141,7 +142,7 @@ impl<'tcx> Visitor<'tcx> for SameItemPushVisitor<'_, 'tcx> {
ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::If(..) => self.non_deterministic_expr = true,
ExprKind::Block(block, _) => self.visit_block(block),
_ => {
if let Some(hir_id) = path_to_local(expr) {
if let Some(hir_id) = expr.res_local_id() {
self.used_locals.insert(hir_id);
}
walk_expr(self, expr);
@ -186,7 +187,7 @@ fn get_vec_push<'tcx>(
&& let ExprKind::MethodCall(path, self_expr, [pushed_item], _) = &semi_stmt.kind
// Check that the method being called is push() on a Vec
&& path.ident.name == sym::push
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec)
&& cx.typeck_results().expr_ty(self_expr).is_diag_item(cx, sym::Vec)
{
return Some((self_expr, pushed_item, semi_stmt.span.ctxt()));
}

View file

@ -1,7 +1,7 @@
use super::UNUSED_ENUMERATE_INDEX;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{pat_is_wild, sugg};
use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, arg: &Expr<'_
&& let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind
&& let ty = cx.typeck_results().expr_ty(arg)
&& pat_is_wild(cx, &index.kind, body)
&& is_type_diagnostic_item(cx, ty, sym::Enumerate)
&& ty.is_diag_item(cx, sym::Enumerate)
&& let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id)
&& cx.tcx.is_diagnostic_item(sym::enumerate_method, call_id)
{

View file

@ -1,5 +1,6 @@
use clippy_utils::res::MaybeResPath;
use clippy_utils::ty::{has_iter_method, implements_trait};
use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
use clippy_utils::{get_parent_expr, is_integer_const, sugg};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{Visitor, walk_expr, walk_local};
@ -47,7 +48,7 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for IncrementVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
// If node is a variable
if let Some(def_id) = path_to_local(expr) {
if let Some(def_id) = expr.res_local_id() {
if let Some(parent) = get_parent_expr(self.cx, expr) {
let state = self.states.entry(def_id).or_insert(IncrementVisitorVarState::Initial);
if *state == IncrementVisitorVarState::IncrOnce {
@ -175,7 +176,7 @@ impl<'tcx> Visitor<'tcx> for InitializeVisitor<'_, 'tcx> {
}
// If node is the desired variable, see how it's used
if path_to_local_id(expr, self.var_id) {
if expr.res_local_id() == Some(self.var_id) {
if self.past_loop {
self.state = InitializeVisitorState::DontWarn;
return;

View file

@ -2,9 +2,10 @@ use std::ops::ControlFlow;
use super::WHILE_LET_ON_ITERATOR;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::visitors::is_res_used;
use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method};
use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{Visitor, walk_expr};
@ -19,11 +20,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr)
// check for `Some(..)` pattern
&& let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind
&& is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
&& cx.qpath_res(pat_path, let_pat.hir_id).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
// check for call to `Iterator::next`
&& let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind
&& method_name.ident.name == sym::next
&& is_trait_method(cx, let_expr, sym::Iterator)
&& cx.ty_based_def(let_expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
&& let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr)
// get the loop containing the match expression
&& !uses_iter(cx, &iter_expr_struct, if_then)

View file

@ -2,9 +2,10 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::If;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::HasSession as _;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, peel_and_count_ty_refs};
use clippy_utils::ty::peel_and_count_ty_refs;
use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
@ -104,7 +105,7 @@ impl ManualAbsDiff {
fn are_ty_eligible<'tcx>(&self, cx: &LateContext<'tcx>, a: &Expr<'_>, b: &Expr<'_>) -> Option<(Ty<'tcx>, usize)> {
let is_int = |ty: Ty<'_>| matches!(ty.kind(), ty::Uint(_) | ty::Int(_)) && self.msrv.meets(cx, msrvs::ABS_DIFF);
let is_duration =
|ty| is_type_diagnostic_item(cx, ty, sym::Duration) && self.msrv.meets(cx, msrvs::DURATION_ABS_DIFF);
|ty: Ty<'_>| ty.is_diag_item(cx, sym::Duration) && self.msrv.meets(cx, msrvs::DURATION_ABS_DIFF);
let a_ty = cx.typeck_results().expr_ty(a).peel_refs();
let (b_ty, b_n_refs, _) = peel_and_count_ty_refs(cx.typeck_results().expr_ty(b));

View file

@ -3,13 +3,11 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::higher::If;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeResPath, MaybeTypeckRes};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::is_const_evaluatable;
use clippy_utils::{
MaybePath, eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id,
peel_blocks, peel_blocks_with_stmt, sym,
};
use clippy_utils::{eq_expr_value, is_in_const_context, peel_blocks, peel_blocks_with_stmt, sym};
use itertools::Itertools;
use rustc_errors::{Applicability, Diag};
use rustc_hir::def::Res;
@ -292,10 +290,12 @@ fn is_if_elseif_else_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx
/// # ;
/// ```
fn is_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
if let ExprKind::MethodCall(seg_second, receiver, [arg_second], _) = &expr.kind
&& (cx.typeck_results().expr_ty_adjusted(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord))
if let ExprKind::MethodCall(seg_second, receiver, [arg_second], _) = expr.kind
&& (cx.typeck_results().expr_ty_adjusted(receiver).is_floating_point()
|| cx.ty_based_def(expr).assoc_fn_parent(cx).is_diag_item(cx, sym::Ord))
&& let ExprKind::MethodCall(seg_first, input, [arg_first], _) = &receiver.kind
&& (cx.typeck_results().expr_ty_adjusted(input).is_floating_point() || is_trait_method(cx, receiver, sym::Ord))
&& (cx.typeck_results().expr_ty_adjusted(input).is_floating_point()
|| cx.ty_based_def(receiver).assoc_fn_parent(cx).is_diag_item(cx, sym::Ord))
{
let is_float = cx.typeck_results().expr_ty_adjusted(input).is_floating_point();
let (min, max) = match (seg_first.ident.name, seg_second.ident.name) {
@ -331,18 +331,18 @@ fn is_call_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
fn segment<'tcx>(cx: &LateContext<'_>, func: &Expr<'tcx>) -> Option<FunctionType<'tcx>> {
match func.kind {
ExprKind::Path(QPath::Resolved(None, path)) => {
let id = path.res.opt_def_id()?;
match cx.tcx.get_diagnostic_name(id) {
let def = path.res.opt_def(cx)?;
match cx.tcx.get_diagnostic_name(def.1) {
Some(sym::cmp_min) => Some(FunctionType::CmpMin),
Some(sym::cmp_max) => Some(FunctionType::CmpMax),
_ if is_diag_trait_item(cx, id, sym::Ord) => {
_ if def.assoc_fn_parent(cx).is_diag_item(cx, sym::Ord) => {
Some(FunctionType::OrdOrFloat(path.segments.last().expect("infallible")))
},
_ => None,
}
},
ExprKind::Path(QPath::TypeRelative(ty, seg)) => {
matches!(path_res(cx, ty), Res::PrimTy(PrimTy::Float(_))).then(|| FunctionType::OrdOrFloat(seg))
matches!(ty.basic_res(), Res::PrimTy(PrimTy::Float(_))).then(|| FunctionType::OrdOrFloat(seg))
},
_ => None,
}
@ -435,7 +435,7 @@ fn is_match_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Opt
let first = BinaryOp::new(first)?;
let second = BinaryOp::new(second)?;
if let PatKind::Binding(_, binding, _, None) = &last_arm.pat.kind
&& path_to_local_id(peel_blocks_with_stmt(last_arm.body), *binding)
&& peel_blocks_with_stmt(last_arm.body).res_local_id() == Some(*binding)
&& last_arm.guard.is_none()
{
// Proceed as normal
@ -516,7 +516,7 @@ fn is_two_if_pattern<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) ->
},
span: first_expr.span.to(second_expr.span),
make_assignment: Some(maybe_input_first_path),
hir_with_ignore_attr: Some(first_expr.hir_id()),
hir_with_ignore_attr: Some(first_expr.hir_id),
})
} else {
None
@ -655,8 +655,8 @@ fn is_clamp_meta_pattern<'tcx>(
let (min, max) = (second_expr, first_expr);
let refers_to_input = match input_hir_ids {
Some((first_hir_id, second_hir_id)) => {
path_to_local_id(peel_blocks(first_bin.left), first_hir_id)
&& path_to_local_id(peel_blocks(second_bin.left), second_hir_id)
peel_blocks(first_bin.left).res_local_id() == Some(first_hir_id)
&& peel_blocks(second_bin.left).res_local_id() == Some(second_hir_id)
},
None => eq_expr_value(cx, first_bin.left, second_bin.left),
};

View file

@ -1,9 +1,10 @@
use clippy_config::Conf;
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{is_from_proc_macro, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@ -138,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
// Checking all possible scenarios using a function would be a hopeless task, as we have
// 16 possible alignments of constants/operands. For now, let's use `partition`.
&& let mut exprs = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs]
&& exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2
&& exprs.iter_mut().partition_in_place(|i| i.res_local_id().is_some()) == 2
&& !expr.span.in_external_macro(cx.sess().source_map())
&& (
is_not_const(cx.tcx, cx.tcx.hir_enclosing_body_owner(expr.hir_id).into())
@ -149,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
&& let ctxt = expr.span.ctxt()
&& let Some(const_1) = ecx.eval_local(const_1, ctxt)
&& let Some(const_2) = ecx.eval_local(const_2, ctxt)
&& path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s))
&& first.res_local_id().is_some_and(|f| second.res_local_id().is_some_and(|s| f == s))
// The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in
// case somebody does that for some reason
&& (const_1.is_pos_infinity() && const_2.is_neg_infinity()

View file

@ -1,9 +1,10 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeResPath, MaybeTypeckRes};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::sym;
use clippy_utils::visitors::{is_local_used, local_used_once};
use clippy_utils::{is_trait_method, path_to_local_id, sym};
use rustc_errors::Applicability;
use rustc_hir::{BindingMode, ExprKind, LetStmt, Node, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
@ -81,8 +82,8 @@ impl LateLintPass<'_> for ManualHashOne {
&& !hash_expr.span.from_expansion()
&& let ExprKind::MethodCall(seg, hashed_value, [ref_to_hasher], _) = hash_expr.kind
&& seg.ident.name == sym::hash
&& is_trait_method(cx, hash_expr, sym::Hash)
&& path_to_local_id(ref_to_hasher.peel_borrows(), hasher)
&& cx.ty_based_def(hash_expr).opt_parent(cx).is_diag_item(cx, sym::Hash)
&& ref_to_hasher.peel_borrows().res_local_id() == Some(hasher)
&& let maybe_finish_stmt = stmts.next()
// There should be no more statements referencing `hasher`

View file

@ -1,8 +1,8 @@
use crate::manual_ignore_case_cmp::MatchType::{Literal, ToAscii};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sym;
use clippy_utils::ty::{get_type_diagnostic_name, is_type_diagnostic_item, is_type_lang_item};
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::ExprKind::{Binary, Lit, MethodCall};
@ -58,7 +58,7 @@ fn get_ascii_type<'a>(cx: &LateContext<'a>, kind: rustc_hir::ExprKind<'_>) -> Op
if needs_ref_to_cmp(cx, ty)
|| ty.is_str()
|| ty.is_slice()
|| matches!(get_type_diagnostic_name(cx, ty), Some(sym::OsStr | sym::OsString))
|| matches!(ty.opt_diag_name(cx), Some(sym::OsStr | sym::OsString))
{
return Some((expr.span, ToAscii(is_lower, ty_raw)));
}
@ -72,8 +72,8 @@ fn get_ascii_type<'a>(cx: &LateContext<'a>, kind: rustc_hir::ExprKind<'_>) -> Op
fn needs_ref_to_cmp(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
ty.is_char()
|| *ty.kind() == ty::Uint(UintTy::U8)
|| is_type_diagnostic_item(cx, ty, sym::Vec)
|| is_type_lang_item(cx, ty, LangItem::String)
|| ty.is_diag_item(cx, sym::Vec)
|| ty.is_lang_item(cx, LangItem::String)
}
impl LateLintPass<'_> for ManualIgnoreCaseCmp {

View file

@ -2,8 +2,9 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::sugg::Sugg;
use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators, sym};
use clippy_utils::{higher, is_in_const_context, peel_ref_operators, sym};
use rustc_ast::LitKind::{Byte, Char};
use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
@ -125,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
}
fn get_ty_sugg<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'_>) -> Option<(Span, Ty<'tcx>)> {
let local_hid = path_to_local(arg)?;
let local_hid = arg.res_local_id()?;
if let Node::Param(Param { ty_span, span, .. }) = cx.tcx.parent_hir_node(local_hid)
// `ty_span` and `span` are the same for inferred type, thus a type suggestion must be given
&& ty_span == span

View file

@ -2,16 +2,14 @@ use crate::question_mark::{QUESTION_MARK, QuestionMark};
use clippy_config::types::MatchLintBehaviour;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{
MaybePath, is_lint_allowed, is_never_expr, is_wild, msrvs, pat_and_expr_can_be_question_mark, path_res, peel_blocks,
};
use clippy_utils::{is_lint_allowed, is_never_expr, is_wild, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
use rustc_ast::BindingMode;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, HirId, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_hir::{Arm, Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LintContext};
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
@ -131,39 +129,25 @@ fn is_arms_disjointed(cx: &LateContext<'_>, arm1: &Arm<'_>, arm2: &Arm<'_>) -> b
/// Returns `true` if the given pattern is a variant of an enum.
pub fn is_enum_variant(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
struct Pat<'hir>(&'hir rustc_hir::Pat<'hir>);
impl<'hir> MaybePath<'hir> for Pat<'hir> {
fn qpath_opt(&self) -> Option<&QPath<'hir>> {
match self.0.kind {
PatKind::Struct(ref qpath, fields, _)
if fields
.iter()
.all(|field| is_wild(field.pat) || matches!(field.pat.kind, PatKind::Binding(..))) =>
{
Some(qpath)
},
PatKind::TupleStruct(ref qpath, pats, _)
if pats
.iter()
.all(|pat| is_wild(pat) || matches!(pat.kind, PatKind::Binding(..))) =>
{
Some(qpath)
},
PatKind::Expr(&PatExpr {
kind: PatExprKind::Path(ref qpath),
..
}) => Some(qpath),
_ => None,
}
}
fn hir_id(&self) -> HirId {
self.0.hir_id
}
}
let res = path_res(cx, &Pat(pat));
let path = match pat.kind {
PatKind::Struct(ref qpath, fields, _)
if fields
.iter()
.all(|field| is_wild(field.pat) || matches!(field.pat.kind, PatKind::Binding(..))) =>
{
(qpath, pat.hir_id)
},
PatKind::TupleStruct(ref qpath, pats, _)
if pats
.iter()
.all(|pat| is_wild(pat) || matches!(pat.kind, PatKind::Binding(..))) =>
{
(qpath, pat.hir_id)
},
PatKind::Expr(e) if let Some((qpath, id)) = e.opt_qpath() => (qpath, id),
_ => return false,
};
let res = path.res(cx);
matches!(
res,
Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
@ -384,7 +368,7 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: boo
}
let ty = typeck_results.pat_ty(pat);
// Option and Result are allowed, everything else isn't.
if !(is_type_diagnostic_item(cx, ty, sym::Option) || is_type_diagnostic_item(cx, ty, sym::Result)) {
if !(ty.is_diag_item(cx, sym::Option) || ty.is_diag_item(cx, sym::Result)) {
has_disallowed = true;
}
});

View file

@ -1,7 +1,8 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::{is_trait_method, peel_hir_expr_refs};
use clippy_utils::peel_hir_expr_refs;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind, Mutability, QPath};
@ -52,7 +53,7 @@ impl LateLintPass<'_> for ManualMainSeparatorStr {
&& path.ident.name == sym::to_string
&& let ExprKind::Path(QPath::Resolved(None, path)) = receiver.kind
&& let Res::Def(DefKind::Const, receiver_def_id) = path.res
&& is_trait_method(cx, target, sym::ToString)
&& cx.ty_based_def(target).opt_parent(cx).is_diag_item(cx, sym::ToString)
&& cx.tcx.is_diagnostic_item(sym::path_main_separator, receiver_def_id)
&& let ty::Ref(_, ty, Mutability::Not) = cx.typeck_results().expr_ty_adjusted(expr).kind()
&& ty.is_str()

View file

@ -1,6 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::msrvs::Msrv;
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
use clippy_utils::{is_none_pattern, msrvs, peel_hir_expr_refs, sym};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -189,7 +190,7 @@ fn check_arms(cx: &LateContext<'_>, none_arm: &Arm<'_>, some_arm: &Arm<'_>) -> b
fn returns_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
match expr.kind {
ExprKind::Path(_) => clippy_utils::is_path_diagnostic_item(cx, expr, sym::default_fn),
ExprKind::Path(_) => expr.res(cx).is_diag_item(cx, sym::default_fn),
ExprKind::Closure(cl) => is_empty_slice(cx, cx.tcx.hir_body(cl.body).value),
_ => false,
}
@ -214,11 +215,11 @@ fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
_ => false,
},
ExprKind::Array([]) => true,
ExprKind::Call(def, []) => clippy_utils::is_path_diagnostic_item(cx, def, sym::default_fn),
ExprKind::Call(def, []) => def.res(cx).is_diag_item(cx, sym::default_fn),
_ => false,
}
}
fn is_slice_from_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
clippy_utils::is_path_diagnostic_item(cx, expr, sym::slice_from_ref)
expr.basic_res().is_diag_item(cx, sym::slice_from_ref)
}

View file

@ -1,9 +1,10 @@
use clippy_config::Conf;
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_in_const_context;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet_with_context;
use clippy_utils::{is_in_const_context, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -64,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
&& let ExprKind::Binary(rem2_op, rem2_lhs, rem2_rhs) = add_other.kind
&& rem2_op.node == BinOpKind::Rem
&& const1 == const2
&& let Some(hir_id) = path_to_local(rem2_lhs)
&& let Some(hir_id) = rem2_lhs.res_local_id()
&& let Some(const3) = check_for_unsigned_int_constant(cx, ctxt, rem2_rhs)
// Also ensures the const is nonzero since zero can't be a divisor
&& const2 == const3

View file

@ -2,8 +2,8 @@ use clippy_config::Conf;
use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet;
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::ExprKind::Assign;
@ -189,7 +189,7 @@ fn check_to_owned(
&& let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
&& cx.tcx.is_diagnostic_item(sym::str_chars, chars_expr_def_id)
&& let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
&& is_type_lang_item(cx, ty, hir::LangItem::String)
&& ty.is_lang_item(cx, hir::LangItem::String)
&& SpanlessEq::new(cx).eq_expr(left_expr, str_expr)
&& let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
&& let hir::ExprKind::Closure(closure) = closure_expr.kind
@ -250,7 +250,7 @@ fn match_acceptable_sym(cx: &LateContext<'_>, collect_def_id: DefId) -> bool {
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Msrv) -> bool {
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
let required = match get_type_diagnostic_name(cx, ty) {
let required = match ty.opt_diag_name(cx) {
Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN,
Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN,
Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN,
@ -264,7 +264,7 @@ fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Msrv)
fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap))
matches!(ty.opt_diag_name(cx), Some(sym::BTreeMap | sym::HashMap))
}
fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{iter_input_pats, method_chain_args};
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -205,9 +205,9 @@ fn lint_map_unit_fn(
) {
let var_arg = &map_args.0;
let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) {
let (map_type, variant, lint) = if cx.typeck_results().expr_ty(var_arg).is_diag_item(cx, sym::Option) {
("Option", "Some", OPTION_MAP_UNIT_FN)
} else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Result) {
} else if cx.typeck_results().expr_ty(var_arg).is_diag_item(cx, sym::Result) {
("Result", "Ok", RESULT_MAP_UNIT_FN)
} else {
return;

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{higher, is_res_lang_ctor, sym};
use clippy_utils::{higher, sym};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, PatKind};
use rustc_lint::{LateContext, LateLintPass};
@ -57,8 +57,8 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind //check is expr.ok() has type Result<T,E>.ok(, _)
&& let PatKind::TupleStruct(ref pat_path, [ok_pat], _) = let_pat.kind //get operation
&& ok_path.ident.name == sym::ok
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
&& is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
&& cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result)
&& cx.qpath_res(pat_path, let_pat.hir_id).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
&& let ctxt = expr.span.ctxt()
&& let_expr.span.ctxt() == ctxt
&& let_pat.span.ctxt() == ctxt

View file

@ -1,12 +1,10 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::msrvs::Msrv;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{
SpanlessEq, get_ref_operators, is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt,
peel_ref_operators,
};
use clippy_utils::{SpanlessEq, get_ref_operators, is_unit_expr, peel_blocks_with_stmt, peel_ref_operators};
use rustc_ast::BorrowKind;
use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
@ -67,7 +65,7 @@ fn check_arm<'tcx>(
&& outer_pat.span.eq_ctxt(inner_scrutinee.span)
// match expression must be a local binding
// match <local> { .. }
&& let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee))
&& let Some(binding_id) = peel_ref_operators(cx, inner_scrutinee).res_local_id()
&& !pat_contains_disallowed_or(cx, inner_then_pat, msrv)
// the binding must come from the pattern of the containing match arm
// ..<local>.. => match <local> { .. }
@ -136,7 +134,10 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
kind: PatExprKind::Path(qpath),
hir_id,
..
}) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone),
}) => cx
.qpath_res(qpath, *hir_id)
.ctor_parent(cx)
.is_lang_item(cx, OptionNone),
_ => false,
}
}

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs};
use clippy_utils::{peel_blocks, strip_pat_refs};
use rustc_errors::Applicability;
use rustc_hir::{ExprKind, LetStmt, MatchSource, PatKind, QPath};
use rustc_lint::LateContext;
@ -17,7 +18,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool {
&& args.len() == 1
&& let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind
&& let body = peel_blocks(arms[0].body)
&& path_to_local_id(body, arg)
&& body.res_local_id() == Some(arg)
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(

View file

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
use clippy_utils::visitors::contains_unsafe_block;
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
@ -66,15 +65,15 @@ fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr:
&& let ExprKind::Call(callee, [arg]) = inner_expr.kind
{
return ctxt == expr.span.ctxt()
&& is_res_lang_ctor(cx, path_res(cx, callee), OptionSome)
&& path_to_local_id(arg, target);
&& callee.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
&& arg.res_local_id() == Some(target);
}
false
}
fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) {
return is_res_lang_ctor(cx, path_res(cx, inner_expr), OptionNone);
return inner_expr.res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone);
}
false
}
@ -98,7 +97,7 @@ pub(super) fn check_match<'tcx>(
expr: &'tcx Expr<'_>,
) {
let ty = cx.typeck_results().expr_ty(expr);
if is_type_diagnostic_item(cx, ty, sym::Option)
if ty.is_diag_item(cx, sym::Option)
&& let [first_arm, second_arm] = arms
&& first_arm.guard.is_none()
&& second_arm.guard.is_none()

View file

@ -2,8 +2,7 @@ use super::MANUAL_MAP;
use super::manual_utils::{SomeExpr, check_with};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{is_res_lang_ctor, path_res};
use clippy_utils::res::{MaybeDef, MaybeQPath};
use rustc_hir::LangItem::OptionSome;
use rustc_hir::{Arm, Block, BlockCheckMode, Expr, ExprKind, Pat, UnsafeSource};
use rustc_lint::LateContext;
@ -91,7 +90,7 @@ fn get_some_expr<'tcx>(
// TODO: Allow more complex expressions.
match expr.kind {
ExprKind::Call(callee, [arg])
if ctxt == expr.span.ctxt() && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) =>
if ctxt == expr.span.ctxt() && callee.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome) =>
{
Some(SomeExpr::new_no_negated(arg, needs_unsafe_block))
},

View file

@ -1,8 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::{indent_of, reindent_multiline};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{option_arg_ty, peel_and_count_ty_refs};
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res, peel_blocks, span_contains_comment};
use clippy_utils::{get_parent_expr, peel_blocks, span_contains_comment};
use rustc_ast::{BindingMode, Mutability};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
@ -72,7 +73,10 @@ fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool
true
},
PatKind::TupleStruct(qpath, ..) => {
is_res_lang_ctor(cx, cx.qpath_res(&qpath, pat.hir_id), ResultErr) == must_match_err
cx.qpath_res(&qpath, pat.hir_id)
.ctor_parent(cx)
.is_lang_item(cx, ResultErr)
== must_match_err
},
PatKind::Binding(_, _, _, Some(pat)) | PatKind::Ref(pat, _) => {
is_variant_or_wildcard(cx, pat, can_be_wild, must_match_err)
@ -103,7 +107,7 @@ fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'
/// Check if `expr` contains `Some(ident)`, possibly as a block
fn is_some_ident<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, ident: &Ident, ty: Ty<'tcx>) -> bool {
if let ExprKind::Call(body_callee, [body_arg]) = peel_blocks(expr).kind
&& is_res_lang_ctor(cx, path_res(cx, body_callee), OptionSome)
&& body_callee.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
&& cx.typeck_results().expr_ty(body_arg) == ty
&& let ExprKind::Path(QPath::Resolved(
_,
@ -120,7 +124,7 @@ fn is_some_ident<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, ident: &Ident, t
/// Check if `expr` is `None`, possibly as a block
fn is_none(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
is_res_lang_ctor(cx, path_res(cx, peel_blocks(expr)), OptionNone)
peel_blocks(expr).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
}
/// Suggest replacing `expr` by `scrutinee.METHOD()`, where `METHOD` is either `ok` or

View file

@ -1,4 +1,5 @@
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::{SpanRangeExt as _, indent_of, reindent_multiline};
use rustc_ast::{BindingMode, ByRef};
use rustc_errors::Applicability;
@ -10,8 +11,8 @@ use rustc_span::sym;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{expr_type_is_certain, get_type_diagnostic_name, implements_trait};
use clippy_utils::{is_default_equivalent, is_lint_allowed, path_res, peel_blocks, span_contains_comment};
use clippy_utils::ty::{expr_type_is_certain, implements_trait};
use clippy_utils::{is_default_equivalent, is_lint_allowed, peel_blocks, span_contains_comment};
use super::{MANUAL_UNWRAP_OR, MANUAL_UNWRAP_OR_DEFAULT};
@ -114,7 +115,8 @@ fn handle(
&& is_default_equivalent(cx, peel_blocks(body_none))
{
// We now check if the condition is a None variant, in which case we need to specify the type
if path_res(cx, condition)
if condition
.res(cx)
.opt_def_id()
.is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant())
{
@ -174,7 +176,7 @@ fn handle(
}
fn find_type_name<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'static str> {
match get_type_diagnostic_name(cx, ty)? {
match ty.opt_diag_name(cx)? {
sym::Option => Some("Option"),
sym::Result => Some("Result"),
_ => None,

View file

@ -1,11 +1,12 @@
use crate::map_unit_fn::OPTION_MAP_UNIT_FN;
use crate::matches::MATCH_AS_REF;
use clippy_utils::res::{MaybeDef, MaybeQPath, MaybeResPath};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, is_unsafe_fn, peel_and_count_ty_refs};
use clippy_utils::ty::{is_copy, is_unsafe_fn, peel_and_count_ty_refs};
use clippy_utils::{
CaptureKind, can_move_expr_to_closure, expr_requires_coercion, is_else_clause, is_lint_allowed, is_res_lang_ctor,
path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
CaptureKind, can_move_expr_to_closure, expr_requires_coercion, is_else_clause, is_lint_allowed, peel_blocks,
peel_hir_expr_refs, peel_hir_expr_while,
};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
@ -33,8 +34,7 @@ where
let (scrutinee_ty, ty_ref_count, ty_mutability) = peel_and_count_ty_refs(cx.typeck_results().expr_ty(scrutinee));
let ty_mutability = ty_mutability.unwrap_or(Mutability::Mut);
if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::Option)
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Option))
if !(scrutinee_ty.is_diag_item(cx, sym::Option) && cx.typeck_results().expr_ty(expr).is_diag_item(cx, sym::Option))
{
return None;
}
@ -138,7 +138,7 @@ where
{
snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
} else {
if path_to_local_id(some_expr.expr, id)
if some_expr.expr.res_local_id() == Some(id)
&& !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
&& binding_ref.is_some()
{
@ -190,7 +190,7 @@ pub struct SuggInfo<'a> {
fn can_pass_as_func<'tcx>(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
match expr.kind {
ExprKind::Call(func, [arg])
if path_to_local_id(arg, binding)
if arg.res_local_id() == Some(binding)
&& cx.typeck_results().expr_adjustments(arg).is_empty()
&& !is_unsafe_fn(cx, cx.typeck_results().expr_ty(func).peel_refs()) =>
{
@ -259,9 +259,19 @@ pub(super) fn try_parse_pattern<'tcx>(
kind: PatExprKind::Path(qpath),
hir_id,
..
}) if is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone) => Some(OptionPat::None),
}) if cx
.qpath_res(qpath, *hir_id)
.ctor_parent(cx)
.is_lang_item(cx, OptionNone) =>
{
Some(OptionPat::None)
},
PatKind::TupleStruct(ref qpath, [pattern], _)
if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt =>
if cx
.qpath_res(qpath, pat.hir_id)
.ctor_parent(cx)
.is_lang_item(cx, OptionSome)
&& pat.span.ctxt() == ctxt =>
{
Some(OptionPat::Some { pattern, ref_count })
},
@ -273,5 +283,5 @@ pub(super) fn try_parse_pattern<'tcx>(
// Checks for the `None` value.
fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
is_res_lang_ctor(cx, path_res(cx, peel_blocks(expr)), OptionNone)
peel_blocks(expr).res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
}

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_none_arm, is_res_lang_ctor, path_res, peel_blocks};
use clippy_utils::{is_none_arm, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
use rustc_lint::LateContext;
@ -58,10 +59,13 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome)
&& cx
.qpath_res(qpath, arm.pat.hir_id)
.ctor_parent(cx)
.is_lang_item(cx, LangItem::OptionSome)
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
&& is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome)
&& e.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
&& let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind
&& path2.segments.len() == 1
&& ident.name == path2.segments[0].ident.name

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{SpanlessEq, fulfill_or_allowed, hash_expr, is_lint_allowed, path_to_local, search_same};
use clippy_utils::{SpanlessEq, fulfill_or_allowed, hash_expr, is_lint_allowed, search_same};
use core::cmp::Ordering;
use core::{iter, slice};
use itertools::Itertools;
@ -61,8 +62,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| {
let mut local_map: HirIdMap<HirId> = HirIdMap::default();
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
if let Some(a_id) = path_to_local(a)
&& let Some(b_id) = path_to_local(b)
if let Some(a_id) = a.res_local_id()
&& let Some(b_id) = b.res_local_id()
&& let entry = match local_map.entry(a_id) {
HirIdMapEntry::Vacant(entry) => entry,
// check if using the same bindings as before

View file

@ -1,8 +1,8 @@
use std::ops::ControlFlow;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::sym;
use clippy_utils::ty::is_type_lang_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{Visitor, walk_expr};
@ -58,7 +58,7 @@ impl MatchExprVisitor<'_, '_> {
if let Some(case_method) = get_case_method(segment_ident) {
let ty = self.cx.typeck_results().expr_ty(receiver).peel_refs();
if is_type_lang_item(self.cx, ty, LangItem::String) || ty.kind() == &ty::Str {
if ty.is_lang_item(self.cx, LangItem::String) || ty.kind() == &ty::Str {
return ControlFlow::Break(case_method);
}
}

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
use rustc_errors::Applicability;
use rustc_hir::def::{CtorKind, DefKind, Res};
@ -16,8 +16,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
let ty = cx.typeck_results().expr_ty(ex).peel_refs();
let adt_def = match ty.kind() {
ty::Adt(adt_def, _)
if adt_def.is_enum()
&& !(is_type_diagnostic_item(cx, ty, sym::Option) || is_type_diagnostic_item(cx, ty, sym::Result)) =>
if adt_def.is_enum() && !(ty.is_diag_item(cx, sym::Option) || ty.is_diag_item(cx, sym::Result)) =>
{
adt_def
},

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::macros::{is_panic, root_macro_call};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{is_in_const_context, is_wild, peel_blocks_with_stmt};
use rustc_hir::{Arm, Expr, PatKind};
@ -16,7 +16,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
}
let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs();
if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
if ex_ty.is_diag_item(cx, sym::Result) {
for arm in arms {
if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
let path_str = rustc_hir_pretty::qpath_to_string(&cx.tcx, path);

View file

@ -1,10 +1,10 @@
use super::NEEDLESS_MATCH;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, same_type_modulo_regions};
use clippy_utils::ty::same_type_modulo_regions;
use clippy_utils::{
SpanlessEq, eq_expr_value, get_parent_expr_for_hir, higher, is_else_clause, is_res_lang_ctor, over, path_res,
peel_blocks_with_stmt,
SpanlessEq, eq_expr_value, get_parent_expr_for_hir, higher, is_else_clause, over, peel_blocks_with_stmt,
};
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
@ -104,8 +104,8 @@ fn check_if_let_inner(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool
return false;
}
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
return is_res_lang_ctor(cx, path_res(cx, else_expr), OptionNone)
if let_expr_ty.is_diag_item(cx, sym::Option) {
return else_expr.res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone)
|| eq_expr_value(cx, if_let.let_expr, else_expr);
}
return eq_expr_value(cx, if_let.let_expr, else_expr);

View file

@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::msrvs::Msrv;
use clippy_utils::res::MaybeResPath;
use clippy_utils::source::snippet;
use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used};
use clippy_utils::{is_in_const_context, path_to_local, sym};
use clippy_utils::{is_in_const_context, sym};
use rustc_ast::{BorrowKind, LitKind};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@ -164,7 +165,7 @@ fn get_pat_binding<'tcx>(
guard_expr: &Expr<'_>,
outer_arm: &Arm<'tcx>,
) -> Option<PatBindingInfo> {
if let Some(local) = path_to_local(guard_expr)
if let Some(local) = guard_expr.res_local_id()
&& !is_local_used(cx, outer_arm.body, local)
{
let mut span = None;

View file

@ -1,10 +1,11 @@
use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::source::walk_span_to_context;
use clippy_utils::sugg::{Sugg, make_unop};
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
use clippy_utils::ty::needs_ordered_drop;
use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures};
use clippy_utils::{higher, is_expn_of, is_trait_method, sym};
use clippy_utils::{higher, is_expn_of, sym};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
@ -216,7 +217,7 @@ fn find_method_sugg_for_if_let<'tcx>(
if keyword == "while"
&& let ExprKind::MethodCall(method_path, _, [], _) = let_expr.kind
&& method_path.ident.name == sym::next
&& is_trait_method(cx, let_expr, sym::Iterator)
&& cx.ty_based_def(let_expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
{
return;
}
@ -460,7 +461,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
Item::Diag(expected_ty, expected_variant) => {
let ty = cx.typeck_results().pat_ty(pat);
if is_type_diagnostic_item(cx, ty, expected_ty) {
if ty.is_diag_item(cx, expected_ty) {
let variant = ty
.ty_adt_def()
.expect("struct pattern type is not an ADT")

View file

@ -1,7 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_parent_expr;
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::option_arg_ty;
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
use rustc_errors::Applicability;
use rustc_hir::LangItem::ResultErr;
use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
@ -25,7 +26,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
&& let ExprKind::Path(ref match_fun_path) = match_fun.kind
&& matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..))
&& let ExprKind::Call(err_fun, [err_arg]) = try_arg.kind
&& is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr)
&& err_fun.res(cx).ctor_parent(cx).is_lang_item(cx, ResultErr)
&& let Some(return_ty) = find_return_type(cx, &expr.kind)
{
let (prefix, suffix, err_ty) = if let Some(ty) = result_error_type(cx, return_ty) {

View file

@ -1,12 +1,11 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeQPath};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_non_aggregate_primitive_type;
use clippy_utils::{
is_default_equivalent, is_expr_used_or_unified, is_res_lang_ctor, path_res, peel_ref_operators, std_or_core,
};
use clippy_utils::{is_default_equivalent, is_expr_used_or_unified, peel_ref_operators, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind};
@ -129,7 +128,7 @@ impl_lint_pass!(MemReplace =>
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_OPTION_WITH_SOME, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) -> bool {
if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
if src.res(cx).ctor_parent(cx).is_lang_item(cx, OptionNone) {
// Since this is a late pass (already type-checked),
// and we already know that the second argument is an
// `Option`, we do not need to check the first
@ -163,7 +162,7 @@ fn check_replace_option_with_some(
msrv: Msrv,
) -> bool {
if let ExprKind::Call(src_func, [src_arg]) = src.kind
&& is_res_lang_ctor(cx, path_res(cx, src_func), OptionSome)
&& src_func.res(cx).ctor_parent(cx).is_lang_item(cx, OptionSome)
&& msrv.meets(cx, msrvs::OPTION_REPLACE)
{
// We do not have to check for a `const` context here, because `core::mem::replace()` and

View file

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::{MaybeDef, MaybeResPath};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs};
use clippy_utils::{peel_blocks, peel_ref_operators, strip_pat_refs};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind};
use rustc_lint::LateContext;
@ -23,10 +23,14 @@ pub(super) fn check<'tcx>(
&& let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind
&& let ExprKind::Binary(ref op, l, r) = body.value.kind
&& op.node == BinOpKind::Eq
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv).peel_refs(), sym::SliceIter)
&& cx
.typeck_results()
.expr_ty(filter_recv)
.peel_refs()
.is_diag_item(cx, sym::SliceIter)
&& let operand_is_arg = (|expr| {
let expr = peel_ref_operators(cx, peel_blocks(expr));
path_to_local_id(expr, arg_id)
expr.res_local_id() == Some(arg_id)
})
&& let needle = if operand_is_arg(l) {
r

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(
&& let Some(impl_id) = cx.tcx.impl_of_assoc(bytes_id)
&& cx.tcx.type_of(impl_id).instantiate_identity().is_str()
&& let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs()
&& (ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String))
&& (ty.is_str() || ty.is_lang_item(cx, hir::LangItem::String))
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sym;
use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
use rustc_hir::{Expr, LangItem};
use rustc_lint::LateContext;
@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
let caller_type = if ty.is_str() {
"str"
} else if is_type_lang_item(cx, ty, LangItem::String) {
} else if ty.is_lang_item(cx, LangItem::String) {
"String"
} else {
return;

View file

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
use clippy_utils::sym;
use clippy_utils::ty::is_type_lang_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
@ -43,7 +43,7 @@ pub(super) fn check<'tcx>(
|| ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit()))
&& !ext_str.chars().skip(1).all(|c| c.is_ascii_digit())
&& let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs()
&& (recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String))
&& (recv_ty.is_str() || recv_ty.is_lang_item(cx, LangItem::String))
{
span_lint_and_then(
cx,

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::method_chain_args;
use clippy_utils::res::MaybeQPath;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{method_chain_args, path_def_id};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, Lint};
@ -17,7 +18,7 @@ pub(super) fn check(
) -> bool {
if let Some(args) = method_chain_args(info.chain, chain_methods)
&& let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind
&& let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id))
&& let Some(id) = fun.res(cx).opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id))
&& Some(id) == cx.tcx.lang_items().option_some_variant()
{
let mut applicability = Applicability::MachineApplicable;

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_range_full;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::res::MaybeDef;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, QPath};
use rustc_lint::LateContext;
@ -29,9 +29,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
fn match_acceptable_type(cx: &LateContext<'_>, expr: &Expr<'_>, types: &[rustc_span::Symbol]) -> bool {
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty))
types.iter().any(|&ty| expr_ty.is_diag_item(cx, ty))
// String type is a lang item but not a diagnostic item for now so we need a separate check
|| is_type_lang_item(cx, expr_ty, LangItem::String)
|| expr_ty.is_lang_item(cx, LangItem::String)
}
fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) {

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_trait_method;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::ty::{get_iterator_item_ty, is_copy};
use rustc_errors::Applicability;
use rustc_hir::Expr;
@ -19,7 +19,9 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span,
{
subst.type_at(0)
},
_ if is_trait_method(cx, expr, sym::Iterator) && msrv.meets(cx, msrvs::ITERATOR_COPIED) => {
_ if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
&& msrv.meets(cx, msrvs::ITERATOR_COPIED) =>
{
match get_iterator_item_ty(cx, recv_ty) {
// <T as Iterator>::Item
Some(ty) => ty,

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
use clippy_utils::ty::{has_non_owning_mutable_access, implements_trait};
use clippy_utils::{is_mutable, is_trait_method, path_to_local_with_projections, sym};
use clippy_utils::{is_mutable, path_to_local_with_projections, sym};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Node, PatKind};
use rustc_lint::LateContext;
@ -13,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp
let typeck = cx.typeck_results();
// if the "last" method is that of Iterator
if is_trait_method(cx, expr, sym::Iterator)
if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
// if self implements DoubleEndedIterator
&& let Some(deiter_id) = cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator)
&& let self_type = cx.typeck_results().expr_ty(self_expr)

View file

@ -1,7 +1,7 @@
use crate::methods::DRAIN_COLLECT;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{is_range_full, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
@ -35,8 +35,8 @@ fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>
/// Checks `std::string::String`
fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool {
is_type_lang_item(cx, expr, LangItem::String)
&& is_type_lang_item(cx, recv, LangItem::String)
expr.is_lang_item(cx, LangItem::String)
&& recv.is_lang_item(cx, LangItem::String)
&& matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path)))
}

View file

@ -1,7 +1,8 @@
use super::ERR_EXPECT;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
use clippy_utils::res::MaybeDef;
use clippy_utils::ty::has_debug_impl;
use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_middle::ty;
@ -16,7 +17,7 @@ pub(super) fn check(
err_span: Span,
msrv: Msrv,
) {
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result)
// Grabs the `Result<T, E>` type
&& let result_type = cx.typeck_results().expr_ty(recv)
// Tests if the T type in a `Result<T, E>` is not None
@ -40,7 +41,7 @@ pub(super) fn check(
/// Given a `Result<T, E>` type, return its data (`T`).
fn get_data_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
match ty.kind() {
ty::Adt(_, args) if is_type_diagnostic_item(cx, ty, sym::Result) => args.types().next(),
ty::Adt(_, args) if ty.is_diag_item(cx, sym::Result) => args.types().next(),
_ => None,
}
}

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macro_call_first_node};
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{contains_return, is_inside_always_const_context, peel_blocks};
use rustc_errors::Applicability;
@ -26,9 +26,9 @@ pub(super) fn check<'tcx>(
let arg_root = get_arg_root(cx, arg);
if contains_call(cx, arg_root) && !contains_return(arg_root) {
let receiver_type = cx.typeck_results().expr_ty_adjusted(receiver);
let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::Option) {
let closure_args = if receiver_type.is_diag_item(cx, sym::Option) {
"||"
} else if is_type_diagnostic_item(cx, receiver_type, sym::Result) {
} else if receiver_type.is_diag_item(cx, sym::Result) {
"|_|"
} else {
return;
@ -83,7 +83,7 @@ fn get_arg_root<'a>(cx: &LateContext<'_>, arg: &'a hir::Expr<'a>) -> &'a hir::Ex
if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && {
let arg_type = cx.typeck_results().expr_ty(receiver);
let base_type = arg_type.peel_refs();
base_type.is_str() || is_type_lang_item(cx, base_type, hir::LangItem::String)
base_type.is_str() || base_type.is_lang_item(cx, hir::LangItem::String)
} {
receiver
} else {

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sym;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;
@ -10,7 +10,7 @@ use super::EXTEND_WITH_DRAIN;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) {
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
if is_type_diagnostic_item(cx, ty, sym::Vec)
if ty.is_diag_item(cx, sym::Vec)
//check source object
&& let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind
&& src_method.ident.name == sym::drain
@ -18,10 +18,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
//check if actual src type is mutable for code suggestion
&& let immutable = src_ty.is_mutable_ptr()
&& let src_ty = src_ty.peel_refs()
&& is_type_diagnostic_item(cx, src_ty, sym::Vec)
&& src_ty.is_diag_item(cx, sym::Vec)
//check drain range
&& let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs()
&& is_type_lang_item(cx, src_ty_range, LangItem::RangeFull)
&& src_ty_range.is_lang_item(cx, LangItem::RangeFull)
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_parent_expr;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::res::MaybeDef;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::{Span, sym};
@ -10,7 +10,7 @@ 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_type_diagnostic_item(cx, ty, sym::FileType) {
if !ty.is_diag_item(cx, sym::FileType) {
return;
}

Some files were not shown because too many files have changed in this diff Show more