1
Fork 0

Auto merge of #11694 - flip1995:rustup, r=flip1995

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2023-10-21 11:48:55 +00:00
commit 2b030eb03d
83 changed files with 315 additions and 377 deletions

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath}; use rustc_hir::{AsyncCoroutineKind, Body, BodyId, CoroutineKind, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -45,10 +45,10 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]);
impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
use AsyncGeneratorKind::{Block, Closure}; use AsyncCoroutineKind::{Block, Closure};
// For functions, with explicitly defined types, don't warn. // For functions, with explicitly defined types, don't warn.
// XXXkhuey maybe we should? // XXXkhuey maybe we should?
if let Some(GeneratorKind::Async(Block | Closure)) = body.generator_kind { if let Some(CoroutineKind::Async(Block | Closure)) = body.coroutine_kind {
if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() {
let body_id = BodyId { let body_id = BodyId {
hir_id: body.value.hir_id, hir_id: body.value.hir_id,

View file

@ -183,7 +183,7 @@ declare_clippy_lint! {
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
/// Checks for empty lines after documenation comments. /// Checks for empty lines after documentation comments.
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// The documentation comment was most likely meant to be an inner attribute or regular comment. /// The documentation comment was most likely meant to be an inner attribute or regular comment.
@ -795,7 +795,7 @@ impl EarlyLintPass for EarlyAttributes {
/// Check for empty lines after outer attributes. /// Check for empty lines after outer attributes.
/// ///
/// Attributes and documenation comments are both considered outer attributes /// Attributes and documentation comments are both considered outer attributes
/// by the AST. However, the average user likely considers them to be different. /// by the AST. However, the average user likely considers them to be different.
/// Checking for empty lines after each of these attributes is split into two different /// Checking for empty lines after each of these attributes is split into two different
/// lints but can share the same logic. /// lints but can share the same logic.

View file

@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths}; use clippy_utils::{match_def_path, paths};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, Body, GeneratorKind}; use rustc_hir::{AsyncCoroutineKind, Body, CoroutineKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::GeneratorLayout; use rustc_middle::mir::CoroutineLayout;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span}; use rustc_span::{sym, Span};
@ -195,26 +195,26 @@ impl LateLintPass<'_> for AwaitHolding {
} }
fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
use AsyncGeneratorKind::{Block, Closure, Fn}; use AsyncCoroutineKind::{Block, Closure, Fn};
if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind { if let Some(CoroutineKind::Async(Block | Closure | Fn)) = body.coroutine_kind {
let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let def_id = cx.tcx.hir().body_owner_def_id(body.id());
if let Some(generator_layout) = cx.tcx.mir_generator_witnesses(def_id) { if let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(def_id) {
self.check_interior_types(cx, generator_layout); self.check_interior_types(cx, coroutine_layout);
} }
} }
} }
} }
impl AwaitHolding { impl AwaitHolding {
fn check_interior_types(&self, cx: &LateContext<'_>, generator: &GeneratorLayout<'_>) { fn check_interior_types(&self, cx: &LateContext<'_>, coroutine: &CoroutineLayout<'_>) {
for (ty_index, ty_cause) in generator.field_tys.iter_enumerated() { for (ty_index, ty_cause) in coroutine.field_tys.iter_enumerated() {
if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() { if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
let await_points = || { let await_points = || {
generator coroutine
.variant_source_info .variant_source_info
.iter_enumerated() .iter_enumerated()
.filter_map(|(variant, source_info)| { .filter_map(|(variant, source_info)| {
generator.variant_fields[variant] coroutine.variant_fields[variant]
.raw .raw
.contains(&ty_index) .contains(&ty_index)
.then_some(source_info.span) .then_some(source_info.span)
@ -287,5 +287,8 @@ fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
} }
fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool { fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool {
match_def_path(cx, def_id, &paths::REFCELL_REF) || match_def_path(cx, def_id, &paths::REFCELL_REFMUT) matches!(
cx.tcx.get_diagnostic_name(def_id),
Some(sym::RefCellRef | sym::RefCellRefMut)
)
} }

View file

@ -1,8 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::macro_backtrace; use clippy_utils::macros::macro_backtrace;
use clippy_utils::ty::expr_sig; use clippy_utils::ty::expr_sig;
use clippy_utils::{get_parent_node, is_default_equivalent, match_path, path_def_id, paths}; use clippy_utils::{get_parent_node, is_default_equivalent, path_def_id};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::intravisit::{walk_ty, Visitor};
use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind}; use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -55,7 +56,7 @@ impl LateLintPass<'_> for BoxDefault {
expr.span, expr.span,
"`Box::new(_)` of default value", "`Box::new(_)` of default value",
"try", "try",
if is_plain_default(arg_path) || given_type(cx, expr) { if is_plain_default(cx, arg_path) || given_type(cx, expr) {
"Box::default()".into() "Box::default()".into()
} else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
@ -68,11 +69,13 @@ impl LateLintPass<'_> for BoxDefault {
} }
} }
fn is_plain_default(arg_path: &Expr<'_>) -> bool { fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
// we need to match the actual path so we don't match e.g. "u8::default" // we need to match the actual path so we don't match e.g. "u8::default"
if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind { if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind
&& let Res::Def(_, def_id) = path.res
{
// avoid generic parameters // avoid generic parameters
match_path(path, &paths::DEFAULT_TRAIT_METHOD) && path.segments.iter().all(|seg| seg.args.is_none()) cx.tcx.is_diagnostic_item(sym::default_fn, def_id) && path.segments.iter().all(|seg| seg.args.is_none())
} else { } else {
false false
} }

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_c_void; use clippy_utils::ty::is_c_void;
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, match_any_def_paths, paths}; use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant};
use rustc_hir::{Expr, ExprKind, GenericArg}; use rustc_hir::{Expr, ExprKind, GenericArg};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
@ -75,16 +75,17 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
} }
}, },
ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => { ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => {
static PATHS: &[&[&str]] = &[
paths::PTR_READ_UNALIGNED.as_slice(),
paths::PTR_UNALIGNED_VOLATILE_LOAD.as_slice(),
paths::PTR_UNALIGNED_VOLATILE_STORE.as_slice(),
];
if let ExprKind::Path(path) = &func.kind if let ExprKind::Path(path) = &func.kind
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
&& (match_any_def_paths(cx, def_id, PATHS).is_some() && matches!(
|| cx.tcx.is_diagnostic_item(sym::ptr_write_unaligned, def_id)) cx.tcx.get_diagnostic_name(def_id),
Some(
sym::ptr_write_unaligned
| sym::ptr_read_unaligned
| sym::intrinsics_unaligned_volatile_load
| sym::intrinsics_unaligned_volatile_store
)
)
{ {
true true
} else { } else {

View file

@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::sym;
use super::CAST_SLICE_FROM_RAW_PARTS; use super::CAST_SLICE_FROM_RAW_PARTS;
@ -17,12 +17,10 @@ enum RawPartsKind {
} }
fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option<RawPartsKind> { fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option<RawPartsKind> {
if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS) { match cx.tcx.get_diagnostic_name(did)? {
Some(RawPartsKind::Immutable) sym::slice_from_raw_parts => Some(RawPartsKind::Immutable),
} else if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS_MUT) { sym::slice_from_raw_parts_mut => Some(RawPartsKind::Mutable),
Some(RawPartsKind::Mutable) _ => None,
} else {
None
} }
} }

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -37,7 +37,7 @@ impl LateLintPass<'_> for CreateDir {
if let ExprKind::Call(func, [arg, ..]) = expr.kind; if let ExprKind::Call(func, [arg, ..]) = expr.kind;
if let ExprKind::Path(ref path) = func.kind; if let ExprKind::Path(ref path) = func.kind;
if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR); if cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id);
then { then {
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,

View file

@ -1,9 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_drop, is_copy}; use clippy_utils::ty::{has_drop, is_copy};
use clippy_utils::{ use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths,
};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -14,7 +12,7 @@ use rustc_middle::ty;
use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{Ident, Symbol}; use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span; use rustc_span::{sym, Span};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -91,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
if let ExprKind::Path(ref qpath) = path.kind; if let ExprKind::Path(ref qpath) = path.kind;
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
if !is_update_syntax_base(cx, expr); if !is_update_syntax_base(cx, expr);
// Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type. // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
if let QPath::Resolved(None, _path) = qpath; if let QPath::Resolved(None, _path) = qpath;
@ -268,7 +266,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
then { then {
// right hand side of assignment is `Default::default` // right hand side of assignment is `Default::default`
match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD) cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
} else { } else {
false false
} }

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{is_ty_alias, match_def_path, paths}; use clippy_utils::is_ty_alias;
use hir::def::Res; use hir::def::Res;
use hir::ExprKind; use hir::ExprKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -7,6 +7,7 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -63,7 +64,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
// `<Foo as Bar>::Assoc` cannot be used as a constructor // `<Foo as Bar>::Assoc` cannot be used as a constructor
if !is_alias(*base); if !is_alias(*base);
if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
// make sure we have a struct with no fields (unit struct) // make sure we have a struct with no fields (unit struct)
if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
if def.is_struct(); if def.is_struct();

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::last_path_segment;
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::{last_path_segment, match_def_path, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::SyntaxContext; use rustc_span::{sym, SyntaxContext};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -37,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
&& let TyKind::Path(ty_path) = &ty.kind && let TyKind::Path(ty_path) = &ty.kind
&& let QPath::Resolved(None, path) = ty_path && let QPath::Resolved(None, path) = ty_path
&& let def::Res::Def(_, def_id) = &path.res && let def::Res::Def(_, def_id) = &path.res
&& match_def_path(cx, *def_id, &paths::ITER_EMPTY) && cx.tcx.is_diagnostic_item(sym::IterEmpty, *def_id)
&& let ctxt = expr.span.ctxt() && let ctxt = expr.span.ctxt()
&& ty.span.ctxt() == ctxt && ty.span.ctxt() == ctxt
{ {

View file

@ -701,7 +701,7 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
if let Some(parent) = get_parent_expr(cx, e) if let Some(parent) = get_parent_expr(cx, e)
&& parent.span.ctxt() == e.span.ctxt() && parent.span.eq_ctxt(e.span)
{ {
match parent.kind { match parent.kind {
ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _) ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _)
@ -842,8 +842,8 @@ impl TyCoercionStability {
| ty::Adt(..) | ty::Adt(..)
| ty::Foreign(_) | ty::Foreign(_)
| ty::FnDef(..) | ty::FnDef(..)
| ty::Generator(..) | ty::Coroutine(..)
| ty::GeneratorWitness(..) | ty::CoroutineWitness(..)
| ty::Closure(..) | ty::Closure(..)
| ty::Never | ty::Never
| ty::Tuple(_) | ty::Tuple(_)

View file

@ -436,8 +436,8 @@ fn lint_for_missing_headers(
let body = cx.tcx.hir().body(body_id); let body = cx.tcx.hir().body(body_id);
let ret_ty = typeck.expr_ty(body.value); let ret_ty = typeck.expr_ty(body.value);
if implements_trait(cx, ret_ty, future, &[]); if implements_trait(cx, ret_ty, future, &[]);
if let ty::Generator(_, subs, _) = ret_ty.kind(); if let ty::Coroutine(_, subs, _) = ret_ty.kind();
if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result); if is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result);
then { then {
span_lint( span_lint(
cx, cx,

View file

@ -241,7 +241,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
}, },
], ],
_, _,
) if key_span.ctxt() == expr.span.ctxt() => { ) if key_span.eq_ctxt(expr.span) => {
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
let expr = ContainsExpr { let expr = ContainsExpr {
negated, negated,

View file

@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use clippy_utils::{is_entrypoint_fn, match_def_path, paths}; use clippy_utils::is_entrypoint_fn;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -45,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
if let ExprKind::Call(path_expr, _args) = e.kind; if let ExprKind::Call(path_expr, _args) = e.kind;
if let ExprKind::Path(ref path) = path_expr.kind; if let ExprKind::Path(ref path) = path_expr.kind;
if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::EXIT); if cx.tcx.is_diagnostic_item(sym::process_exit, def_id);
let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id; let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent); if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent);
// If the next item up is a function we check if it is an entry point // If the next item up is a function we check if it is an entry point

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{find_format_args, format_args_inputs_span}; use clippy_utils::macros::{find_format_args, format_args_inputs_span};
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_expn_of, match_function_call, paths}; use clippy_utils::{is_expn_of, path_def_id};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res; use rustc_hir::def::Res;
@ -47,18 +47,19 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind
&& unwrap_fun.ident.name == sym::unwrap && unwrap_fun.ident.name == sym::unwrap
// match call to write_fmt // match call to write_fmt
&& let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind) && 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) && write_fun.ident.name == sym!(write_fmt)
// match calls to std::io::stdout() / std::io::stderr () && let Some(def_id) = path_def_id(cx, write_recv_path)
&& let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
Some("stdout")
} else if match_function_call(cx, write_recv, &paths::STDERR).is_some() {
Some("stderr")
} else {
None
}
&& let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root())
{ {
// match calls to std::io::stdout() / std::io::stderr ()
let (dest_name, prefix) = match cx.tcx.get_diagnostic_name(def_id) {
Some(sym::io_stdout) => ("stdout", ""),
Some(sym::io_stderr) => ("stderr", "e"),
_ => return,
};
let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { return; };
// ordering is important here, since `writeln!` uses `write!` internally // ordering is important here, since `writeln!` uses `write!` internally
let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() { let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() {
Some("writeln") Some("writeln")
@ -67,11 +68,6 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
} else { } else {
None None
}; };
let prefix = if dest_name == "stderr" {
"e"
} else {
""
};
// We need to remove the last trailing newline from the string because the // We need to remove the last trailing newline from the string because the
// underlying `fmt::write` function doesn't know whether `println!` or `print!` was // underlying `fmt::write` function doesn't know whether `println!` or `print!` was

View file

@ -274,7 +274,7 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) {
for element in array { for element in array {
if_chain! { if_chain! {
if let ExprKind::Binary(ref op, ref lhs, _) = element.kind; if let ExprKind::Binary(ref op, ref lhs, _) = element.kind;
if has_unary_equivalent(op.node) && lhs.span.ctxt() == op.span.ctxt(); if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span);
let space_span = lhs.span.between(op.span); let space_span = lhs.span.between(op.span);
if let Some(space_snippet) = snippet_opt(cx, space_span); if let Some(space_snippet) = snippet_opt(cx, space_span);
let lint_span = lhs.span.with_lo(lhs.span.hi()); let lint_span = lhs.span.with_lo(lhs.span.hi());

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::path_def_id;
use clippy_utils::ty::is_c_void; use clippy_utils::ty::is_c_void;
use clippy_utils::{match_def_path, path_def_id, paths};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, QPath}; use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -68,7 +68,7 @@ fn def_id_matches_type(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static s
} }
} }
if match_def_path(cx, def_id, &paths::WEAK_RC) || match_def_path(cx, def_id, &paths::WEAK_ARC) { if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RcWeak | sym::ArcWeak)) {
Some("Weak") Some("Weak")
} else { } else {
None None

View file

@ -130,11 +130,7 @@ fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
fn is_an_instant(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn is_an_instant(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let expr_ty = cx.typeck_results().expr_ty(expr); let expr_ty = cx.typeck_results().expr_ty(expr);
ty::is_type_diagnostic_item(cx, expr_ty, sym::Instant)
match expr_ty.kind() {
rustc_middle::ty::Adt(def, _) => clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT),
_ => false,
}
} }
fn is_a_duration(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn is_a_duration(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {

View file

@ -12,7 +12,7 @@ declare_clippy_lint! {
/// It checks for the size of a `Future` created by `async fn` or `async {}`. /// It checks for the size of a `Future` created by `async fn` or `async {}`.
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Generator`, /// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Coroutine`,
/// large size of a `Future` may cause stack overflows. /// large size of a `Future` may cause stack overflows.
/// ///
/// ### Example /// ### Example

View file

@ -31,7 +31,7 @@ impl LateLintPass<'_> for UnderscoreTyped {
if !in_external_macro(cx.tcx.sess, local.span); if !in_external_macro(cx.tcx.sess, local.span);
if let Some(ty) = local.ty; // Ensure that it has a type defined if let Some(ty) = local.ty; // Ensure that it has a type defined
if let TyKind::Infer = &ty.kind; // that type is '_' if let TyKind::Infer = &ty.kind; // that type is '_'
if local.span.ctxt() == ty.span.ctxt(); if local.span.eq_ctxt(ty.span);
then { then {
// NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
// this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::match_type; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths}; use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Body, Closure, Expr, ExprKind}; use rustc_hir::{Body, Closure, Expr, ExprKind};
@ -62,7 +62,7 @@ impl LateLintPass<'_> for LinesFilterMapOk {
if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind && if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind &&
is_trait_method(cx, expr, sym::Iterator) && is_trait_method(cx, expr, sym::Iterator) &&
(fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") && (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") &&
match_type(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), &paths::STD_IO_LINES) is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines)
{ {
let lint = match &fm_arg.kind { let lint = match &fm_arg.kind {
// Detect `Result::ok` // Detect `Result::ok`

View file

@ -4,7 +4,7 @@ use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{ use rustc_hir::{
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, AsyncCoroutineKind, Block, Body, Closure, CoroutineKind, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, GenericBound,
ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -188,7 +188,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
.. ..
} = block_expr; } = block_expr;
let closure_body = cx.tcx.hir().body(body); let closure_body = cx.tcx.hir().body(body);
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block)); if closure_body.coroutine_kind == Some(CoroutineKind::Async(AsyncCoroutineKind::Block));
then { then {
return Some(closure_body); return Some(closure_body);
} }

View file

@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
if !in_external_macro(cx.sess(), expr.span) if !in_external_macro(cx.sess(), expr.span)
&& ( && (
matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst) matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst)
|| cx.tcx.features().active(sym!(const_float_classify)) || cx.tcx.features().declared(sym!(const_float_classify))
) && let ExprKind::Binary(kind, lhs, rhs) = expr.kind ) && let ExprKind::Binary(kind, lhs, rhs) = expr.kind
&& let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind
&& let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind && let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind

View file

@ -59,7 +59,7 @@ impl<'tcx> QuestionMark {
let Some(init) = local.init && let Some(init) = local.init &&
local.els.is_none() && local.els.is_none() &&
local.ty.is_none() && local.ty.is_none() &&
init.span.ctxt() == stmt.span.ctxt() && init.span.eq_ctxt(stmt.span) &&
let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init)
{ {
match if_let_or_match { match if_let_or_match {

View file

@ -135,7 +135,7 @@ fn check_to_owned(
if msrv.meets(msrvs::STRING_RETAIN) if msrv.meets(msrvs::STRING_RETAIN)
&& let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
&& let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
&& match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD) && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id)
&& let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
&& let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id) && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER) && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)

View file

@ -57,7 +57,7 @@ fn check_arm<'tcx>(
} }
}, },
}; };
if outer_pat.span.ctxt() == inner_scrutinee.span.ctxt(); if outer_pat.span.eq_ctxt(inner_scrutinee.span);
// match expression must be a local binding // match expression must be a local binding
// match <local> { .. } // match <local> { .. }
if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)); if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee));

View file

@ -119,7 +119,7 @@ where
// it's being passed by value. // it's being passed by value.
let scrutinee = peel_hir_expr_refs(scrutinee).0; let scrutinee = peel_hir_expr_refs(scrutinee).0;
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX {
format!("({scrutinee_str})") format!("({scrutinee_str})")
} else { } else {
scrutinee_str.into() scrutinee_str.into()
@ -130,7 +130,7 @@ where
if_chain! { if_chain! {
if !some_expr.needs_unsafe_block; if !some_expr.needs_unsafe_block;
if let Some(func) = can_pass_as_func(cx, id, some_expr.expr); if let Some(func) = can_pass_as_func(cx, id, some_expr.expr);
if func.span.ctxt() == some_expr.expr.span.ctxt(); if func.span.eq_ctxt(some_expr.expr.span);
then { then {
snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
} else { } else {

View file

@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
if is_type_diagnostic_item(cx, ex_ty, sym::Result) { if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
for arm in arms { for arm in arms {
if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind { if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)); let path_str = rustc_hir_pretty::qpath_to_string(path);
if path_str == "Err" { if path_str == "Err" {
let mut matching_wild = inner.iter().any(is_wild); let mut matching_wild = inner.iter().any(is_wild);
let mut ident_bind_name = kw::Underscore; let mut ident_bind_name = kw::Underscore;

View file

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

View file

@ -1,7 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::paths;
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{is_type_diagnostic_item, match_type};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -22,15 +20,14 @@ pub(super) fn check(
} }
let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
if let ty::Adt(_, subst) = obj_ty.kind() { if let ty::Adt(adt, subst) = obj_ty.kind()
let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) { && let Some(name) = cx.tcx.get_diagnostic_name(adt.did())
"Rc" {
} else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) { let caller_type = match name {
"Arc" sym::Rc => "Rc",
} else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { sym::Arc => "Arc",
"Weak" sym::RcWeak | sym::ArcWeak => "Weak",
} else { _ => return,
return;
}; };
// Sometimes unnecessary ::<_> after Rc/Arc/Weak // Sometimes unnecessary ::<_> after Rc/Arc/Weak

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{is_expr_path_def_path, paths, sugg}; use clippy_utils::{is_path_diagnostic_item, sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
@ -13,7 +13,7 @@ use super::FROM_ITER_INSTEAD_OF_COLLECT;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) { pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) {
if_chain! { if_chain! {
if is_expr_path_def_path(cx, func, &paths::FROM_ITERATOR_METHOD); if is_path_diagnostic_item(cx, func, sym::from_iter_fn);
let ty = cx.typeck_results().expr_ty(expr); let ty = cx.typeck_results().expr_ty(expr);
let arg_ty = cx.typeck_results().expr_ty(&args[0]); let arg_ty = cx.typeck_results().expr_ty(&args[0]);
if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);

View file

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth}; use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
@ -22,7 +21,7 @@ pub fn check(
if_chain! { if_chain! {
if args.is_empty() && method_name == sym::to_string; if args.is_empty() && method_name == sym::to_string;
if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD); if cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did);
if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id); if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id);
let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver); let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver);
let self_ty = args.type_at(0); let self_ty = args.type_at(0);

View file

@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(
if_chain! { if_chain! {
if !expr.span.from_expansion(); if !expr.span.from_expansion();
if let ExprKind::Closure(c) = m_arg.kind; if let ExprKind::Closure(c) = m_arg.kind;
if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body); if let Body {params: [p], value: body_expr, coroutine_kind: _ } = cx.tcx.hir().body(c.body);
if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind; if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) { let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::higher::VecArgs; use clippy_utils::higher::VecArgs;
use clippy_utils::{expr_or_init, is_trait_method, match_def_path, paths}; use clippy_utils::{expr_or_init, is_trait_method};
use rustc_ast::LitKind; use rustc_ast::LitKind;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -26,14 +26,14 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) ->
}; };
let did = adt.did(); let did = adt.did();
if match_def_path(cx, did, &paths::ARRAY_INTO_ITER) { if cx.tcx.is_diagnostic_item(sym::ArrayIntoIter, did) {
// For array::IntoIter<T, const N: usize>, the length is the second generic // For array::IntoIter<T, const N: usize>, the length is the second generic
// parameter. // parameter.
substs substs
.const_at(1) .const_at(1)
.try_eval_target_usize(cx.tcx, cx.param_env) .try_eval_target_usize(cx.tcx, cx.param_env)
.map(u128::from) .map(u128::from)
} else if match_def_path(cx, did, &paths::SLICE_ITER) } else if cx.tcx.is_diagnostic_item(sym::SliceIter, did)
&& let ExprKind::MethodCall(_, recv, ..) = iter.kind && let ExprKind::MethodCall(_, recv, ..) = iter.kind
{ {
if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() { if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() {
@ -47,9 +47,9 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) ->
} else { } else {
None None
} }
} else if match_def_path(cx, did, &paths::ITER_EMPTY) { } else if cx.tcx.is_diagnostic_item(sym::IterEmpty, did) {
Some(0) Some(0)
} else if match_def_path(cx, did, &paths::ITER_ONCE) { } else if cx.tcx.is_diagnostic_item(sym::IterOnce, did) {
Some(1) Some(1)
} else { } else {
None None

View file

@ -56,7 +56,7 @@ pub(super) fn check<'tcx>(
// lint, with note if neither arg is > 1 line and both map() and // lint, with note if neither arg is > 1 line and both map() and
// unwrap_or_else() have the same span // unwrap_or_else() have the same span
let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1; let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt(); let same_span = map_arg.span.eq_ctxt(unwrap_arg.span);
if same_span && !multiline { if same_span && !multiline {
let var_snippet = snippet(cx, recv.span, ".."); let var_snippet = snippet(cx, recv.span, "..");
span_lint_and_sugg( span_lint_and_sugg(

View file

@ -1,17 +1,17 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use clippy_utils::paths; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::ty::match_type;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::source_map::{Span, Spanned}; use rustc_span::source_map::{Span, Spanned};
use rustc_span::sym;
use super::NONSENSICAL_OPEN_OPTIONS; use super::NONSENSICAL_OPEN_OPTIONS;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id) && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
&& match_type(cx, cx.tcx.type_of(impl_id).instantiate_identity(), &paths::OPEN_OPTIONS) && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions)
{ {
let mut options = Vec::new(); let mut options = Vec::new();
get_open_options(cx, recv, &mut options); get_open_options(cx, recv, &mut options);
@ -40,7 +40,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
// Only proceed if this is a call on some object of type std::fs::OpenOptions // Only proceed if this is a call on some object of type std::fs::OpenOptions
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && !arguments.is_empty() { if is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions) && !arguments.is_empty() {
let argument_option = match arguments[0].kind { let argument_option = match arguments[0].kind {
ExprKind::Lit(span) => { ExprKind::Lit(span) => {
if let Spanned { if let Spanned {

View file

@ -32,8 +32,7 @@ pub(super) fn check(
return; return;
} }
let deref_aliases: [&[&str]; 8] = [ let deref_aliases: [&[&str]; 7] = [
&paths::DEREF_MUT_TRAIT_METHOD,
&paths::CSTRING_AS_C_STR, &paths::CSTRING_AS_C_STR,
&paths::OS_STRING_AS_OS_STR, &paths::OS_STRING_AS_OS_STR,
&paths::PATH_BUF_AS_PATH, &paths::PATH_BUF_AS_PATH,
@ -49,6 +48,7 @@ pub(super) fn check(
.opt_def_id() .opt_def_id()
.map_or(false, |fun_def_id| { .map_or(false, |fun_def_id| {
cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id) cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
|| deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path)) || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
}) })
}, },
@ -70,6 +70,7 @@ pub(super) fn check(
then { then {
let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap(); let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
cx.tcx.is_diagnostic_item(sym::deref_method, method_did) cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
|| deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
} else { } else {
false false

View file

@ -2,18 +2,19 @@ use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::sym;
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{get_trait_def_id, match_def_path, paths}; use clippy_utils::{match_def_path, paths};
use super::SEEK_FROM_CURRENT; use super::SEEK_FROM_CURRENT;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
let ty = cx.typeck_results().expr_ty(recv); let ty = cx.typeck_results().expr_ty(recv);
if let Some(def_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) { if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) {
if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) { if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability); let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths}; use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
use rustc_ast::ast::{LitIntType, LitKind}; use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::Span; use rustc_span::{sym, Span};
use super::SEEK_TO_START_INSTEAD_OF_REWIND; use super::SEEK_TO_START_INSTEAD_OF_REWIND;
@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
return; return;
} }
if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) && if let Some(seek_trait_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) &&
implements_trait(cx, ty, seek_trait_id, &[]) && implements_trait(cx, ty, seek_trait_id, &[]) &&
let ExprKind::Call(func, args1) = arg.kind && let ExprKind::Call(func, args1) = arg.kind &&
let ExprKind::Path(ref path) = func.kind && let ExprKind::Path(ref path) = func.kind &&

View file

@ -1,9 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::paths; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::ty::match_type;
use rustc_errors::{Applicability, Diagnostic}; use rustc_errors::{Applicability, Diagnostic};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::Span; use rustc_span::{sym, Span};
use {rustc_ast as ast, rustc_hir as hir}; use {rustc_ast as ast, rustc_hir as hir};
use super::SUSPICIOUS_COMMAND_ARG_SPACE; use super::SUSPICIOUS_COMMAND_ARG_SPACE;
@ -11,7 +10,7 @@ use super::SUSPICIOUS_COMMAND_ARG_SPACE;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) { pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) {
let ty = cx.typeck_results().expr_ty(recv).peel_refs(); let ty = cx.typeck_results().expr_ty(recv).peel_refs();
if match_type(cx, ty, &paths::STD_PROCESS_COMMAND) if is_type_diagnostic_item(cx, ty, sym::Command)
&& let hir::ExprKind::Lit(lit) = &arg.kind && let hir::ExprKind::Lit(lit) = &arg.kind
&& let ast::LitKind::Str(s, _) = &lit.node && let ast::LitKind::Str(s, _) = &lit.node
&& let Some((arg1, arg2)) = s.as_str().split_once(' ') && let Some((arg1, arg2)) = s.as_str().split_once(' ')

View file

@ -1,9 +1,9 @@
use std::ops::ControlFlow; use std::ops::ControlFlow;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::match_type; use clippy_utils::is_path_lang_item;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::{for_each_expr, Visitable}; use clippy_utils::visitors::{for_each_expr, Visitable};
use clippy_utils::{is_path_lang_item, paths};
use rustc_ast::LitKind; use rustc_ast::LitKind;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
@ -114,9 +114,11 @@ fn should_lint<'tcx>(
if let ExprKind::MethodCall(path, recv, ..) = &expr.kind { if let ExprKind::MethodCall(path, recv, ..) = &expr.kind {
let recv_ty = typeck_results.expr_ty(recv).peel_refs(); let recv_ty = typeck_results.expr_ty(recv).peel_refs();
if path.ident.name == sym::debug_struct && match_type(cx, recv_ty, &paths::FORMATTER) { if path.ident.name == sym::debug_struct && is_type_diagnostic_item(cx, recv_ty, sym::Formatter) {
has_debug_struct = true; has_debug_struct = true;
} else if path.ident.name == sym!(finish_non_exhaustive) && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) { } else if path.ident.name == sym!(finish_non_exhaustive)
&& is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct)
{
has_finish_non_exhaustive = true; has_finish_non_exhaustive = true;
} }
} }
@ -137,7 +139,7 @@ fn as_field_call<'tcx>(
) -> Option<Symbol> { ) -> Option<Symbol> {
if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind
&& let recv_ty = typeck_results.expr_ty(recv).peel_refs() && let recv_ty = typeck_results.expr_ty(recv).peel_refs()
&& match_type(cx, recv_ty, &paths::DEBUG_STRUCT) && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct)
&& path.ident.name == sym::field && path.ident.name == sym::field
&& let ExprKind::Lit(lit) = &debug_field.kind && let ExprKind::Lit(lit) = &debug_field.kind
&& let LitKind::Str(sym, ..) = lit.node && let LitKind::Str(sym, ..) = lit.node

View file

@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
cx, cx,
arguments.iter().collect(), arguments.iter().collect(),
cx.typeck_results().expr_ty(fn_expr), cx.typeck_results().expr_ty(fn_expr),
&rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)), &rustc_hir_pretty::qpath_to_string(path),
"function", "function",
); );
} }

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::is_self;
use clippy_utils::ptr::get_spans; use clippy_utils::ptr::get_spans;
use clippy_utils::source::{snippet, snippet_opt}; use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::ty::{ use clippy_utils::ty::{
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
}; };
use clippy_utils::{get_trait_def_id, is_self, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_ast::ast::Attribute; use rustc_ast::ast::Attribute;
use rustc_errors::{Applicability, Diagnostic}; use rustc_errors::{Applicability, Diagnostic};
@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
need!(cx.tcx.lang_items().fn_trait()), need!(cx.tcx.lang_items().fn_trait()),
need!(cx.tcx.lang_items().fn_once_trait()), need!(cx.tcx.lang_items().fn_once_trait()),
need!(cx.tcx.lang_items().fn_mut_trait()), need!(cx.tcx.lang_items().fn_mut_trait()),
need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)), need!(cx.tcx.get_diagnostic_item(sym::RangeBounds)),
]; ];
let sized_trait = need!(cx.tcx.lang_items().sized_trait()); let sized_trait = need!(cx.tcx.lang_items().sized_trait());

View file

@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath}; use rustc_hir::{AsyncCoroutineKind, Block, Body, CoroutineKind, Expr, ExprKind, LangItem, MatchSource, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -87,7 +87,7 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
} }
fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) { fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
if let Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) = body.generator_kind { if let Some(CoroutineKind::Async(AsyncCoroutineKind::Fn)) = body.coroutine_kind {
if let ExprKind::Block( if let ExprKind::Block(
Block { Block {
expr: expr:
@ -125,7 +125,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind; if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind;
if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind;
if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind;
if expr.span.ctxt() == inner_expr.span.ctxt(); if expr.span.eq_ctxt(inner_expr.span);
let expr_ty = cx.typeck_results().expr_ty(expr); let expr_ty = cx.typeck_results().expr_ty(expr);
let inner_ty = cx.typeck_results().expr_ty(inner_expr); let inner_ty = cx.typeck_results().expr_ty(inner_expr);
if expr_ty == inner_ty; if expr_ty == inner_ty;

View file

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::paths::ORD_CMP;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, match_def_path, path_res, std_or_core}; use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, path_res, std_or_core};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp}; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp};
@ -261,7 +260,7 @@ fn self_cmp_call<'tcx>(
match cmp_expr.kind { match cmp_expr.kind {
ExprKind::Call(path, [_self, _other]) => path_res(cx, path) ExprKind::Call(path, [_self, _other]) => path_res(cx, path)
.opt_def_id() .opt_def_id()
.is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP)), .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id)),
ExprKind::MethodCall(_, _, [_other], ..) => { ExprKind::MethodCall(_, _, [_other], ..) => {
// We can set this to true here no matter what as if it's a `MethodCall` and goes to the // We can set this to true here no matter what as if it's a `MethodCall` and goes to the
// `else` branch, it must be a method named `cmp` that isn't `Ord::cmp` // `else` branch, it must be a method named `cmp` that isn't `Ord::cmp`
@ -273,7 +272,7 @@ fn self_cmp_call<'tcx>(
cx.tcx cx.tcx
.typeck(def_id) .typeck(def_id)
.type_dependent_def_id(cmp_expr.hir_id) .type_dependent_def_id(cmp_expr.hir_id)
.is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP)) .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id))
}, },
_ => false, _ => false,
} }

View file

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{snippet_opt, snippet_with_applicability}; use clippy_utils::source::{snippet_opt, snippet_with_applicability};
use clippy_utils::ty::{is_type_diagnostic_item, match_type};
use clippy_utils::{match_def_path, paths}; use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -45,15 +44,14 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
match &expr.kind { match &expr.kind {
ExprKind::MethodCall(path, func, [param], _) => { ExprKind::MethodCall(path, func, [param], _) => {
let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
if_chain! { if_chain! {
if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def();
if (path.ident.name == sym!(mode) if (path.ident.name == sym!(mode)
&& (match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder)))
|| is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder))) || (path.ident.name == sym!(set_mode)
|| (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS)); && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()));
if let ExprKind::Lit(_) = param.kind; if let ExprKind::Lit(_) = param.kind;
if param.span.ctxt() == expr.span.ctxt(); if param.span.eq_ctxt(expr.span);
then { then {
let Some(snip) = snippet_opt(cx, param.span) else { let Some(snip) = snippet_opt(cx, param.span) else {
@ -72,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE); if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
if let ExprKind::Lit(_) = param.kind; if let ExprKind::Lit(_) = param.kind;
if param.span.ctxt() == expr.span.ctxt(); if param.span.eq_ctxt(expr.span);
if let Some(snip) = snippet_opt(cx, param.span); if let Some(snip) = snippet_opt(cx, param.span);
if !snip.starts_with("0o"); if !snip.starts_with("0o");
then { then {

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{is_lint_allowed, match_def_path, paths};
use rustc_ast::ImplPolarity; use rustc_ast::ImplPolarity;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{FieldDef, Item, ItemKind, Node}; use rustc_hir::{FieldDef, Item, ItemKind, Node};
@ -233,7 +233,7 @@ fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> b
return true; return true;
}, },
ty::Adt(adt_def, _) => { ty::Adt(adt_def, _) => {
if match_def_path(cx, adt_def.did(), &paths::PTR_NON_NULL) { if cx.tcx.is_diagnostic_item(sym::NonNull, adt_def.did()) {
return true; return true;
} }
}, },

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::path_def_id;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{match_def_path, path_def_id, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -50,7 +50,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
}, },
ExprKind::Call(path, [arg]) ExprKind::Call(path, [arg])
if path_def_id(cx, path).map_or(false, |did| { if path_def_id(cx, path).map_or(false, |did| {
if match_def_path(cx, did, &paths::FROM_STR_METHOD) { if cx.tcx.is_diagnostic_item(sym::from_str_method, did) {
true true
} else if cx.tcx.is_diagnostic_item(sym::from_fn, did) { } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
!is_copy(cx, typeck.expr_ty(expr)) !is_copy(cx, typeck.expr_ty(expr))

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::paths; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::ty::match_type;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -31,7 +31,7 @@ declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALS
impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
&& match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS) && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
&& path.ident.name == sym!(set_readonly) && path.ident.name == sym!(set_readonly)
&& let ExprKind::Lit(lit) = &arg.kind && let ExprKind::Lit(lit) = &arg.kind
&& LitKind::Bool(false) == lit.node && LitKind::Bool(false) == lit.node

View file

@ -4,9 +4,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::expr_sig; use clippy_utils::ty::expr_sig;
use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::visitors::contains_unsafe_block;
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths}; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
use hir::LifetimeName; use hir::LifetimeName;
use if_chain::if_chain;
use rustc_errors::{Applicability, MultiSpan}; use rustc_errors::{Applicability, MultiSpan};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::hir_id::HirIdMap; use rustc_hir::hir_id::HirIdMap;
@ -271,60 +270,43 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
} }
fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B. if let ExprKind::Call(fun, args) = expr.kind
const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 13] = [ && let ExprKind::Path(ref qpath) = fun.kind
(&paths::SLICE_FROM_RAW_PARTS, &[0]), && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
(&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]), && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id)
(&paths::PTR_COPY, &[0, 1]), {
(&paths::PTR_COPY_NONOVERLAPPING, &[0, 1]), // `arg` positions where null would cause U.B.
(&paths::PTR_READ, &[0]), let arg_indices: &[_] = match name {
(&paths::PTR_READ_UNALIGNED, &[0]), sym::ptr_read
(&paths::PTR_READ_VOLATILE, &[0]), | sym::ptr_read_unaligned
(&paths::PTR_REPLACE, &[0]), | sym::ptr_read_volatile
(&paths::PTR_SLICE_FROM_RAW_PARTS, &[0]), | sym::ptr_replace
(&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]), | sym::ptr_slice_from_raw_parts
(&paths::PTR_SWAP, &[0, 1]), | sym::ptr_slice_from_raw_parts_mut
(&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]), | sym::ptr_write
(&paths::PTR_WRITE_BYTES, &[0]), | sym::ptr_write_bytes
]; | sym::ptr_write_unaligned
let invalid_null_ptr_usage_table_diag_items: [(Option<DefId>, &[usize]); 3] = [ | sym::ptr_write_volatile
(cx.tcx.get_diagnostic_item(sym::ptr_write), &[0]), | sym::slice_from_raw_parts
(cx.tcx.get_diagnostic_item(sym::ptr_write_unaligned), &[0]), | sym::slice_from_raw_parts_mut => &[0],
(cx.tcx.get_diagnostic_item(sym::ptr_write_volatile), &[0]), sym::ptr_copy
]; | sym::ptr_copy_nonoverlapping
| sym::ptr_swap
| sym::ptr_swap_nonoverlapping => &[0, 1],
_ => return,
};
if_chain! { for &arg_idx in arg_indices {
if let ExprKind::Call(fun, args) = expr.kind; if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) {
if let ExprKind::Path(ref qpath) = fun.kind; span_lint_and_sugg(
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); cx,
let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>(); INVALID_NULL_PTR_USAGE,
if let Some(arg_indices) = INVALID_NULL_PTR_USAGE_TABLE arg.span,
.iter() "pointer must be non-null",
.find_map(|&(fn_path, indices)| if fn_path == fun_def_path { Some(indices) } else { None }) "change this to",
.or_else(|| { "core::ptr::NonNull::dangling().as_ptr()".to_string(),
invalid_null_ptr_usage_table_diag_items Applicability::MachineApplicable,
.iter() );
.find_map(|&(def_id, indices)| {
if def_id == Some(fun_def_id) {
Some(indices)
} else {
None
}
})
});
then {
for &arg_idx in arg_indices {
if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) {
span_lint_and_sugg(
cx,
INVALID_NULL_PTR_USAGE,
arg.span,
"pointer must be non-null",
"change this to",
"core::ptr::NonNull::dangling().as_ptr()".to_string(),
Applicability::MachineApplicable,
);
}
} }
} }
} }

View file

@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::VecArgs; use clippy_utils::higher::VecArgs;
use clippy_utils::last_path_segment;
use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::source::{indent_of, snippet}; use clippy_utils::source::{indent_of, snippet};
use clippy_utils::ty::match_type;
use clippy_utils::{last_path_segment, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_hir::{Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span, Symbol}; use rustc_span::{sym, Span, Symbol};
@ -133,8 +133,9 @@ fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> {
return Some((symbol, func.span)); return Some((symbol, func.span));
} }
let ty_path = cx.typeck_results().expr_ty(expr); if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind()
if match_type(cx, ty_path, &paths::WEAK_RC) || match_type(cx, ty_path, &paths::WEAK_ARC) { && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak))
{
return Some((Symbol::intern("Weak"), func.span)); return Some((Symbol::intern("Weak"), func.span));
} }
} }

View file

@ -5,7 +5,7 @@ use clippy_utils::peel_blocks;
use clippy_utils::source::{snippet, walk_span_to_context}; use clippy_utils::source::{snippet, walk_span_to_context};
use clippy_utils::visitors::for_each_expr; use clippy_utils::visitors::for_each_expr;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{AsyncGeneratorKind, Closure, Expr, ExprKind, GeneratorKind, MatchSource}; use rustc_hir::{AsyncCoroutineKind, Closure, CoroutineKind, Expr, ExprKind, MatchSource};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::UpvarCapture; use rustc_middle::ty::UpvarCapture;
@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
let Some(body_expr) = desugar_async_block(cx, expr) && let Some(body_expr) = desugar_async_block(cx, expr) &&
let Some(expr) = desugar_await(peel_blocks(body_expr)) && let Some(expr) = desugar_await(peel_blocks(body_expr)) &&
// The await prefix must not come from a macro as its content could change in the future. // The await prefix must not come from a macro as its content could change in the future.
expr.span.ctxt() == body_expr.span.ctxt() && expr.span.eq_ctxt(body_expr.span) &&
// An async block does not have immediate side-effects from a `.await` point-of-view. // An async block does not have immediate side-effects from a `.await` point-of-view.
(!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) &&
let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt())
@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind && if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind &&
let body = cx.tcx.hir().body(*body) && let body = cx.tcx.hir().body(*body) &&
matches!(body.generator_kind, Some(GeneratorKind::Async(AsyncGeneratorKind::Block))) matches!(body.coroutine_kind, Some(CoroutineKind::Async(AsyncCoroutineKind::Block)))
{ {
cx cx
.typeck_results() .typeck_results()

View file

@ -99,8 +99,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));
let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD) let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
|| match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD) || cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id)
|| (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD) || (cx.tcx.is_diagnostic_item(sym::to_string_method, fn_def_id)
&& is_type_lang_item(cx, arg_ty, LangItem::String)); && is_type_lang_item(cx, arg_ty, LangItem::String));
let from_deref = !from_borrow let from_deref = !from_borrow

View file

@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
// without this check, we'd end up linting twice. // without this check, we'd end up linting twice.
&& !matches!(recv.kind, hir::ExprKind::Call(..)) && !matches!(recv.kind, hir::ExprKind::Call(..))
&& let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
&& let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth) && let Some((body, fn_decl, coroutine_kind)) = find_innermost_closure(cx, recv, call_depth)
{ {
span_lint_and_then( span_lint_and_then(
cx, cx,
@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability); let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability);
if generator_kind.is_async() if coroutine_kind.is_async()
&& let hir::ExprKind::Closure(closure) = body.kind && let hir::ExprKind::Closure(closure) = body.kind
{ {
let async_closure_body = cx.tcx.hir().body(closure.body); let async_closure_body = cx.tcx.hir().body(closure.body);

View file

@ -50,7 +50,7 @@ impl EarlyLintPass for DerefAddrOf {
if_chain! { if_chain! {
if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind; if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind;
if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind; if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind;
if deref_target.span.ctxt() == e.span.ctxt(); if deref_target.span.eq_ctxt(e.span);
if !addrof_target.span.from_expansion(); if !addrof_target.span.from_expansion();
then { then {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;

View file

@ -2,7 +2,6 @@
//! expecting a count of T //! expecting a count of T
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -67,16 +66,6 @@ fn get_pointee_ty_and_count_expr<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>,
) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> { ) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
const FUNCTIONS: [&[&str]; 8] = [
&paths::PTR_COPY_NONOVERLAPPING,
&paths::PTR_COPY,
&paths::PTR_WRITE_BYTES,
&paths::PTR_SWAP_NONOVERLAPPING,
&paths::PTR_SLICE_FROM_RAW_PARTS,
&paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
&paths::SLICE_FROM_RAW_PARTS,
&paths::SLICE_FROM_RAW_PARTS_MUT,
];
const METHODS: [&str; 11] = [ const METHODS: [&str; 11] = [
"write_bytes", "write_bytes",
"copy_to", "copy_to",
@ -97,7 +86,16 @@ fn get_pointee_ty_and_count_expr<'tcx>(
if let ExprKind::Call(func, [.., count]) = expr.kind; if let ExprKind::Call(func, [.., count]) = expr.kind;
if let ExprKind::Path(ref func_qpath) = func.kind; if let ExprKind::Path(ref func_qpath) = func.kind;
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path)); if matches!(cx.tcx.get_diagnostic_name(def_id), Some(
sym::ptr_copy
| sym::ptr_copy_nonoverlapping
| sym::ptr_slice_from_raw_parts
| sym::ptr_slice_from_raw_parts_mut
| sym::ptr_swap_nonoverlapping
| sym::ptr_write_bytes
| sym::slice_from_raw_parts
| sym::slice_from_raw_parts_mut
));
// Get the pointee type // Get the pointee type
if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next(); if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next();

View file

@ -33,7 +33,7 @@ impl LateLintPass<'_> for ConfusingXorAndPow {
if !in_external_macro(cx.sess(), expr.span) if !in_external_macro(cx.sess(), expr.span)
&& let ExprKind::Binary(op, left, right) = &expr.kind && let ExprKind::Binary(op, left, right) = &expr.kind
&& op.node == BinOpKind::BitXor && op.node == BinOpKind::BitXor
&& left.span.ctxt() == right.span.ctxt() && left.span.eq_ctxt(right.span)
&& let ExprKind::Lit(lit_left) = &left.kind && let ExprKind::Lit(lit_left) = &left.kind
&& let ExprKind::Lit(lit_right) = &right.kind && let ExprKind::Lit(lit_right) = &right.kind
&& matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..)) && matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..))

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::path_def_id;
use clippy_utils::source::snippet_with_context; use clippy_utils::source::snippet_with_context;
use clippy_utils::{match_def_path, path_def_id, paths};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp}; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{Span, SyntaxContext}; use rustc_span::{sym, Span, SyntaxContext};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -42,7 +42,7 @@ impl LateLintPass<'_> for SwapPtrToRef {
fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
if let ExprKind::Call(fn_expr, [arg1, arg2]) = e.kind if let ExprKind::Call(fn_expr, [arg1, arg2]) = e.kind
&& let Some(fn_id) = path_def_id(cx, fn_expr) && let Some(fn_id) = path_def_id(cx, fn_expr)
&& match_def_path(cx, fn_id, &paths::MEM_SWAP) && cx.tcx.is_diagnostic_item(sym::mem_swap, fn_id)
&& let ctxt = e.span.ctxt() && let ctxt = e.span.ctxt()
&& let (from_ptr1, arg1_span) = is_ptr_to_ref(cx, arg1, ctxt) && let (from_ptr1, arg1_span) = is_ptr_to_ref(cx, arg1, ctxt)
&& let (from_ptr2, arg2_span) = is_ptr_to_ref(cx, arg2, ctxt) && let (from_ptr2, arg2_span) = is_ptr_to_ref(cx, arg2, ctxt)

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -96,7 +96,7 @@ impl LateLintPass<'_> for UnnamedAddress {
if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind;
if let ExprKind::Path(ref func_qpath) = func.kind; if let ExprKind::Path(ref func_qpath) = func.kind;
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::PTR_EQ); if cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id);
let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0); let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0);
if ty_param.is_trait(); if ty_param.is_trait();
then { then {

View file

@ -86,7 +86,7 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
} }
fn visit_body(&mut self, b: &'tcx Body<'tcx>) { fn visit_body(&mut self, b: &'tcx Body<'tcx>) {
let is_async_block = matches!(b.generator_kind, Some(rustc_hir::GeneratorKind::Async(_))); let is_async_block = matches!(b.coroutine_kind, Some(rustc_hir::CoroutineKind::Async(_)));
if is_async_block { if is_async_block {
self.async_depth += 1; self.async_depth += 1;

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{match_type, peel_mid_ty_refs_is_mutable}; use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators}; use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators};
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind}; use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
// Don't lint `Peekable`s returned from a block // Don't lint `Peekable`s returned from a block
if let Some(expr) = block.expr if let Some(expr) = block.expr
&& let Some(ty) = cx.typeck_results().expr_ty_opt(peel_ref_operators(cx, expr)) && let Some(ty) = cx.typeck_results().expr_ty_opt(peel_ref_operators(cx, expr))
&& match_type(cx, ty, &paths::PEEKABLE) && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
{ {
return; return;
} }
@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
&& !init.span.from_expansion() && !init.span.from_expansion()
&& let Some(ty) = cx.typeck_results().expr_ty_opt(init) && let Some(ty) = cx.typeck_results().expr_ty_opt(init)
&& let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty) && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty)
&& match_type(cx, ty, &paths::PEEKABLE) && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
{ {
let mut vis = PeekableVisitor::new(cx, binding); let mut vis = PeekableVisitor::new(cx, binding);
@ -222,7 +222,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
fn arg_is_mut_peekable(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool { fn arg_is_mut_peekable(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
if let Some(ty) = cx.typeck_results().expr_ty_opt(arg) if let Some(ty) = cx.typeck_results().expr_ty_opt(arg)
&& let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty) && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty)
&& match_type(cx, ty, &paths::PEEKABLE) && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
{ {
true true
} else { } else {

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin
use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg; use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths}; use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, path_to_local};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
@ -331,7 +331,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
let a = cx.typeck_results().expr_ty(e); let a = cx.typeck_results().expr_ty(e);
let b = cx.typeck_results().expr_ty(arg); let b = cx.typeck_results().expr_ty(arg);
if_chain! { if_chain! {
if match_def_path(cx, def_id, &paths::TRY_FROM); if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id);
if is_type_diagnostic_item(cx, a, sym::Result); if is_type_diagnostic_item(cx, a, sym::Result);
if let ty::Adt(_, args) = a.kind(); if let ty::Adt(_, args) = a.kind();
if let Some(a_type) = args.types().next(); if let Some(a_type) = args.types().next();

View file

@ -30,7 +30,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
if_chain_local_span(cx, local, if_chain_span), if_chain_local_span(cx, local, if_chain_span),
"`let` expression should be above the `if_chain!`", "`let` expression should be above the `if_chain!`",
); );
} else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) { } else if local.span.eq_ctxt(block.span) && is_if_chain_then(after, block.expr, if_chain_span) {
span_lint( span_lint(
cx, cx,
IF_CHAIN_STYLE, IF_CHAIN_STYLE,

View file

@ -13,6 +13,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::ConstValue; use rustc_middle::mir::ConstValue;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::sym;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use std::borrow::Cow; use std::borrow::Cow;
@ -160,12 +161,8 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
impl InterningDefinedSymbol { impl InterningDefinedSymbol {
fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> { fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> {
static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR, &paths::TO_STRING_METHOD]; static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR];
static SYMBOL_STR_PATHS: &[&[&str]] = &[ static SYMBOL_STR_PATHS: &[&[&str]] = &[&paths::SYMBOL_AS_STR, &paths::SYMBOL_TO_IDENT_STRING];
&paths::SYMBOL_AS_STR,
&paths::SYMBOL_TO_IDENT_STRING,
&paths::TO_STRING_METHOD,
];
let call = if_chain! { let call = if_chain! {
if let ExprKind::AddrOf(_, _, e) = expr.kind; if let ExprKind::AddrOf(_, _, e) = expr.kind;
if let ExprKind::Unary(UnOp::Deref, e) = e.kind; if let ExprKind::Unary(UnOp::Deref, e) = e.kind;
@ -186,9 +183,19 @@ impl InterningDefinedSymbol {
}; };
// ...which converts it to a string // ...which converts it to a string
let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS }; let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS };
if let Some(path) = paths.iter().find(|path| match_def_path(cx, did, path)); if let Some(is_to_owned) = paths
.iter()
.find_map(|path| if match_def_path(cx, did, path) {
Some(path == &paths::SYMBOL_TO_IDENT_STRING)
} else {
None
})
.or_else(|| if cx.tcx.is_diagnostic_item(sym::to_string_method, did) {
Some(true)
} else {
None
});
then { then {
let is_to_owned = path.last().unwrap().ends_with("string");
return Some(SymbolStrExpr::Expr { return Some(SymbolStrExpr::Expr {
item, item,
is_ident, is_ident,

View file

@ -494,7 +494,7 @@ impl SerializableSpan {
let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo()); let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo());
Self { Self {
path: format!("{}", loc.file.name.prefer_remapped()), path: format!("{}", loc.file.name.prefer_remapped_unconditionaly()),
line: loc.line, line: loc.line,
} }
} }

View file

@ -457,7 +457,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
}; };
}, },
ExprKind::Path(QPath::Resolved(_, path)) ExprKind::Path(QPath::Resolved(_, path))
if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD) if cx.tcx.is_diagnostic_item(sym::default_fn, path.res.opt_def_id()?)
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) => && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) =>
{ {
return Some(VecInitKind::Default); return Some(VecInitKind::Default);

View file

@ -2048,21 +2048,33 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
let mut expr = func.value; let mut expr = func.value;
loop { loop {
match expr.kind { match expr.kind {
#[rustfmt::skip] ExprKind::Block(
ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, ) &Block {
| ExprKind::Ret(Some(e)) => expr = e, stmts: [],
#[rustfmt::skip] expr: Some(e),
ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => { ..
if_chain! {
if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
if let ExprKind::Ret(Some(ret_val)) = e.kind;
then {
expr = ret_val;
} else {
return false;
}
}
}, },
_,
)
| ExprKind::Ret(Some(e)) => expr = e,
ExprKind::Block(
&Block {
stmts: [stmt],
expr: None,
..
},
_,
) => {
if_chain! {
if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
if let ExprKind::Ret(Some(ret_val)) = e.kind;
then {
expr = ret_val;
} else {
return false;
}
}
},
_ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(), _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
} }
} }
@ -2081,9 +2093,8 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
}, },
ExprKind::Path(QPath::Resolved(_, path)) ExprKind::Path(QPath::Resolved(_, path))
if path.segments.iter().all(|seg| seg.infer_args) if path.segments.iter().all(|seg| seg.infer_args)
&& let Some(did) = path.res.opt_def_id() => && let Some(did) = path.res.opt_def_id() => {
{ cx.tcx.is_diagnostic_item(sym::convert_identity, did)
match_def_path(cx, did, &paths::CONVERT_IDENTITY)
}, },
_ => false, _ => false,
} }
@ -2100,7 +2111,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
match expr.kind { match expr.kind {
ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)), ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
_ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)), _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
} }
} }

View file

@ -245,7 +245,7 @@ impl<'a> PanicExpn<'a> {
return None; return None;
}; };
let result = match name { let result = match name {
"panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty, "panic" if arg.span.eq_ctxt(expr.span) => Self::Empty,
"panic" | "panic_str" => Self::Str(arg), "panic" | "panic_str" => Self::Str(arg),
"panic_display" | "panic_cold_display" => { "panic_display" | "panic_cold_display" => {
let ExprKind::AddrOf(_, _, e) = &arg.kind else { let ExprKind::AddrOf(_, _, e) = &arg.kind else {

View file

@ -25,17 +25,12 @@ pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]; pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
pub const EXIT: [&str; 3] = ["std", "process", "exit"];
pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"]; pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@ -48,8 +43,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"]; pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"]; pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
pub const ITER_ONCE: [&str; 5] = ["core", "iter", "sources", "once", "Once"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
@ -59,10 +52,8 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"]; pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"]; pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
@ -71,28 +62,9 @@ pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "Rw
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"]; pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
pub const PEEKABLE: [&str; 5] = ["core", "iter", "adapters", "peekable", "Peekable"];
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
#[cfg_attr(not(unix), allow(clippy::invalid_paths))] #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"]; pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"];
pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"];
pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"];
pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"];
pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"];
pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"];
pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"];
pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"];
pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"];
pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"]; pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"]; pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"]; pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
@ -101,21 +73,11 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"]; pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"]; pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"];
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"]; pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"];
pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"];
pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
pub const STD_IO_LINES: [&str; 3] = ["std", "io", "Lines"];
pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"]; pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"]; pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
pub const STD_PROCESS_COMMAND: [&str; 3] = ["std", "process", "Command"];
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"]; pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"]; pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
@ -136,13 +98,10 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol",
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
#[cfg(feature = "internal")] #[cfg(feature = "internal")]
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"]; pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"]; pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"];
pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"]; pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
@ -150,18 +109,10 @@ pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"]; pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"];
pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"]; pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
pub const INSTANT: [&str; 3] = ["std", "time", "Instant"];
pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"]; pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"]; pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"]; pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"]; pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
pub const FORMATTER: [&str; 3] = ["core", "fmt", "Formatter"];
pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"];
pub const ORD_CMP: [&str; 4] = ["core", "cmp", "Ord", "cmp"];
#[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"]; pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
pub const ARRAY_INTO_ITER: [&str; 4] = ["core", "array", "iter", "IntoIter"];

View file

@ -305,8 +305,8 @@ fn check_terminator<'tcx>(
Ok(()) Ok(())
}, },
TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => {
Err((span, "const fn generators are unstable".into())) Err((span, "const fn coroutines are unstable".into()))
}, },
TerminatorKind::Call { TerminatorKind::Call {
func, func,

View file

@ -31,7 +31,7 @@ use rustc_trait_selection::traits::{Obligation, ObligationCause};
use std::assert_matches::debug_assert_matches; use std::assert_matches::debug_assert_matches;
use std::iter; use std::iter;
use crate::{match_def_path, path_res, paths}; use crate::{match_def_path, path_res};
mod type_certainty; mod type_certainty;
pub use type_certainty::expr_type_is_certain; pub use type_certainty::expr_type_is_certain;
@ -461,10 +461,8 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
else if is_type_lang_item(cx, ty, LangItem::OwnedBox) else if is_type_lang_item(cx, ty, LangItem::OwnedBox)
|| matches!( || matches!(
get_type_diagnostic_name(cx, ty), get_type_diagnostic_name(cx, ty),
Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type) Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type | sym::RcWeak | sym::ArcWeak)
) )
|| match_type(cx, ty, &paths::WEAK_RC)
|| match_type(cx, ty, &paths::WEAK_ARC)
{ {
// Check all of the generic arguments. // Check all of the generic arguments.
if let ty::Adt(_, subs) = ty.kind() { if let ty::Adt(_, subs) = ty.kind() {
@ -1135,7 +1133,7 @@ pub fn make_projection<'tcx>(
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
assert_generic_args_match(tcx, assoc_item.def_id, args); assert_generic_args_match(tcx, assoc_item.def_id, args);
Some(tcx.mk_alias_ty(assoc_item.def_id, args)) Some(ty::AliasTy::new(tcx, assoc_item.def_id, args))
} }
helper( helper(
tcx, tcx,

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2023-10-06" channel = "nightly-2023-10-21"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

View file

@ -11,6 +11,6 @@ fn main() {
const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
// Don't lint, not yet a diagnostic or language item // Don't lint, not a diagnostic or language item
const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; const OPS_MOD: [&str; 2] = ["core", "ops"];
} }

View file

@ -13,7 +13,7 @@ error[E0308]: mismatched types
LL | fn foo<u32>(a: u32) -> u32 { LL | fn foo<u32>(a: u32) -> u32 {
| --- --- expected `u32` because of return type | --- --- expected `u32` because of return type
| | | |
| this type parameter | expected this type parameter
LL | 42 LL | 42
| ^^ expected type parameter `u32`, found integer | ^^ expected type parameter `u32`, found integer
| |

View file

@ -1,6 +1,6 @@
// Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562 // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
#![feature(generators, generator_trait)] #![feature(coroutines, coroutine_trait)]
fn main() { fn main() {
let _ = || { let _ = || {

View file

@ -31,7 +31,7 @@ LL | const VAL: T;
| ------------ `VAL` from trait | ------------ `VAL` from trait
... ...
LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {} LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,6 +1,5 @@
#![warn(clippy::implied_bounds_in_impls)] #![warn(clippy::implied_bounds_in_impls)]
#![allow(dead_code)] #![allow(dead_code)]
#![feature(return_position_impl_trait_in_trait)]
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};

View file

@ -1,6 +1,5 @@
#![warn(clippy::implied_bounds_in_impls)] #![warn(clippy::implied_bounds_in_impls)]
#![allow(dead_code)] #![allow(dead_code)]
#![feature(return_position_impl_trait_in_trait)]
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};

View file

@ -1,5 +1,5 @@
error: this bound is already specified as the supertrait of `DerefMut<Target = T>` error: this bound is already specified as the supertrait of `DerefMut<Target = T>`
--> $DIR/implied_bounds_in_impls.rs:13:36 --> $DIR/implied_bounds_in_impls.rs:12:36
| |
LL | fn deref_derefmut<T>(x: T) -> impl Deref<Target = T> + DerefMut<Target = T> { LL | fn deref_derefmut<T>(x: T) -> impl Deref<Target = T> + DerefMut<Target = T> {
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
@ -13,7 +13,7 @@ LL + fn deref_derefmut<T>(x: T) -> impl DerefMut<Target = T> {
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<U, W, U>` error: this bound is already specified as the supertrait of `GenericSubtrait<U, W, U>`
--> $DIR/implied_bounds_in_impls.rs:30:37 --> $DIR/implied_bounds_in_impls.rs:29:37
| |
LL | fn generics_implied<U, W>() -> impl GenericTrait<W> + GenericSubtrait<U, W, U> LL | fn generics_implied<U, W>() -> impl GenericTrait<W> + GenericSubtrait<U, W, U>
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
@ -25,7 +25,7 @@ LL + fn generics_implied<U, W>() -> impl GenericSubtrait<U, W, U>
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>` error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>`
--> $DIR/implied_bounds_in_impls.rs:36:40 --> $DIR/implied_bounds_in_impls.rs:35:40
| |
LL | fn generics_implied_multi<V>() -> impl GenericTrait<i32> + GenericTrait2<V> + GenericSubtrait<(), i32, V> {} LL | fn generics_implied_multi<V>() -> impl GenericTrait<i32> + GenericTrait2<V> + GenericSubtrait<(), i32, V> {}
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
@ -37,7 +37,7 @@ LL + fn generics_implied_multi<V>() -> impl GenericTrait2<V> + GenericSubtrait<(
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>` error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>`
--> $DIR/implied_bounds_in_impls.rs:36:60 --> $DIR/implied_bounds_in_impls.rs:35:60
| |
LL | fn generics_implied_multi<V>() -> impl GenericTrait<i32> + GenericTrait2<V> + GenericSubtrait<(), i32, V> {} LL | fn generics_implied_multi<V>() -> impl GenericTrait<i32> + GenericTrait2<V> + GenericSubtrait<(), i32, V> {}
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@ -49,7 +49,7 @@ LL + fn generics_implied_multi<V>() -> impl GenericTrait<i32> + GenericSubtrait<
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>` error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>`
--> $DIR/implied_bounds_in_impls.rs:38:44 --> $DIR/implied_bounds_in_impls.rs:37:44
| |
LL | fn generics_implied_multi2<T, V>() -> impl GenericTrait<T> + GenericTrait2<V> + GenericSubtrait<(), T, V> LL | fn generics_implied_multi2<T, V>() -> impl GenericTrait<T> + GenericTrait2<V> + GenericSubtrait<(), T, V>
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
@ -61,7 +61,7 @@ LL + fn generics_implied_multi2<T, V>() -> impl GenericTrait2<V> + GenericSubtra
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>` error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>`
--> $DIR/implied_bounds_in_impls.rs:38:62 --> $DIR/implied_bounds_in_impls.rs:37:62
| |
LL | fn generics_implied_multi2<T, V>() -> impl GenericTrait<T> + GenericTrait2<V> + GenericSubtrait<(), T, V> LL | fn generics_implied_multi2<T, V>() -> impl GenericTrait<T> + GenericTrait2<V> + GenericSubtrait<(), T, V>
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@ -73,7 +73,7 @@ LL + fn generics_implied_multi2<T, V>() -> impl GenericTrait<T> + GenericSubtrai
| |
error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, ()>` error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, ()>`
--> $DIR/implied_bounds_in_impls.rs:48:28 --> $DIR/implied_bounds_in_impls.rs:47:28
| |
LL | fn generics_same() -> impl GenericTrait<i32> + GenericSubtrait<(), i32, ()> {} LL | fn generics_same() -> impl GenericTrait<i32> + GenericSubtrait<(), i32, ()> {}
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
@ -85,7 +85,7 @@ LL + fn generics_same() -> impl GenericSubtrait<(), i32, ()> {}
| |
error: this bound is already specified as the supertrait of `DerefMut<Target = u8>` error: this bound is already specified as the supertrait of `DerefMut<Target = u8>`
--> $DIR/implied_bounds_in_impls.rs:52:20 --> $DIR/implied_bounds_in_impls.rs:51:20
| |
LL | fn f() -> impl Deref + DerefMut<Target = u8>; LL | fn f() -> impl Deref + DerefMut<Target = u8>;
| ^^^^^ | ^^^^^
@ -97,7 +97,7 @@ LL + fn f() -> impl DerefMut<Target = u8>;
| |
error: this bound is already specified as the supertrait of `DerefMut<Target = u8>` error: this bound is already specified as the supertrait of `DerefMut<Target = u8>`
--> $DIR/implied_bounds_in_impls.rs:57:20 --> $DIR/implied_bounds_in_impls.rs:56:20
| |
LL | fn f() -> impl Deref + DerefMut<Target = u8> { LL | fn f() -> impl Deref + DerefMut<Target = u8> {
| ^^^^^ | ^^^^^
@ -109,7 +109,7 @@ LL + fn f() -> impl DerefMut<Target = u8> {
| |
error: this bound is already specified as the supertrait of `DerefMut<Target = u8>` error: this bound is already specified as the supertrait of `DerefMut<Target = u8>`
--> $DIR/implied_bounds_in_impls.rs:63:20 --> $DIR/implied_bounds_in_impls.rs:62:20
| |
LL | fn f() -> impl Deref + DerefMut<Target = u8> { LL | fn f() -> impl Deref + DerefMut<Target = u8> {
| ^^^^^ | ^^^^^
@ -121,7 +121,7 @@ LL + fn f() -> impl DerefMut<Target = u8> {
| |
error: this bound is already specified as the supertrait of `PartialOrd` error: this bound is already specified as the supertrait of `PartialOrd`
--> $DIR/implied_bounds_in_impls.rs:74:41 --> $DIR/implied_bounds_in_impls.rs:73:41
| |
LL | fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {} LL | fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {}
| ^^^^^^^^^ | ^^^^^^^^^
@ -133,7 +133,7 @@ LL + fn default_generic_param1() -> impl PartialOrd + Debug {}
| |
error: this bound is already specified as the supertrait of `PartialOrd` error: this bound is already specified as the supertrait of `PartialOrd`
--> $DIR/implied_bounds_in_impls.rs:75:54 --> $DIR/implied_bounds_in_impls.rs:74:54
| |
LL | fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {} LL | fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {}
| ^^^^^^^^^ | ^^^^^^^^^
@ -145,7 +145,7 @@ LL + fn default_generic_param2() -> impl PartialOrd + Debug {}
| |
error: this bound is already specified as the supertrait of `DoubleEndedIterator` error: this bound is already specified as the supertrait of `DoubleEndedIterator`
--> $DIR/implied_bounds_in_impls.rs:88:26 --> $DIR/implied_bounds_in_impls.rs:87:26
| |
LL | fn my_iter() -> impl Iterator<Item = u32> + DoubleEndedIterator { LL | fn my_iter() -> impl Iterator<Item = u32> + DoubleEndedIterator {
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
@ -157,7 +157,7 @@ LL + fn my_iter() -> impl DoubleEndedIterator<Item = u32> {
| |
error: this bound is already specified as the supertrait of `Copy` error: this bound is already specified as the supertrait of `Copy`
--> $DIR/implied_bounds_in_impls.rs:93:27 --> $DIR/implied_bounds_in_impls.rs:92:27
| |
LL | fn f() -> impl Copy + Clone { LL | fn f() -> impl Copy + Clone {
| ^^^^^ | ^^^^^
@ -169,7 +169,7 @@ LL + fn f() -> impl Copy {
| |
error: this bound is already specified as the supertrait of `Trait2<i32>` error: this bound is already specified as the supertrait of `Trait2<i32>`
--> $DIR/implied_bounds_in_impls.rs:107:21 --> $DIR/implied_bounds_in_impls.rs:106:21
| |
LL | fn f2() -> impl Trait1<i32, U = i64> + Trait2<i32> {} LL | fn f2() -> impl Trait1<i32, U = i64> + Trait2<i32> {}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
@ -181,7 +181,7 @@ LL + fn f2() -> impl Trait2<i32, U = i64> {}
| |
error: this bound is already specified as the supertrait of `Trait4<i8, X = i32>` error: this bound is already specified as the supertrait of `Trait4<i8, X = i32>`
--> $DIR/implied_bounds_in_impls.rs:122:21 --> $DIR/implied_bounds_in_impls.rs:121:21
| |
LL | fn f3() -> impl Trait3<i8, i16, i64, X = i32, Y = i128> + Trait4<i8, X = i32> {} LL | fn f3() -> impl Trait3<i8, i16, i64, X = i32, Y = i128> + Trait4<i8, X = i32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,4 +1,4 @@
#![feature(generators)] #![feature(coroutines)]
#![warn(clippy::large_futures)] #![warn(clippy::large_futures)]
#![allow(clippy::never_loop)] #![allow(clippy::never_loop)]
#![allow(clippy::future_not_send)] #![allow(clippy::future_not_send)]

View file

@ -1,4 +1,4 @@
#![feature(generators)] #![feature(coroutines)]
#![warn(clippy::large_futures)] #![warn(clippy::large_futures)]
#![allow(clippy::never_loop)] #![allow(clippy::never_loop)]
#![allow(clippy::future_not_send)] #![allow(clippy::future_not_send)]

View file

@ -1,5 +1,4 @@
#![warn(clippy::unused_async)] #![warn(clippy::unused_async)]
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
use std::future::Future; use std::future::Future;

View file

@ -1,5 +1,5 @@
error: unused `async` for function with no await statements error: unused `async` for function with no await statements
--> $DIR/unused_async.rs:13:5 --> $DIR/unused_async.rs:12:5
| |
LL | / async fn async_block_await() { LL | / async fn async_block_await() {
LL | | LL | |
@ -11,7 +11,7 @@ LL | | }
| |
= help: consider removing the `async` from this function = help: consider removing the `async` from this function
note: `await` used in an async block, which does not require the enclosing function to be `async` note: `await` used in an async block, which does not require the enclosing function to be `async`
--> $DIR/unused_async.rs:16:23 --> $DIR/unused_async.rs:15:23
| |
LL | ready(()).await; LL | ready(()).await;
| ^^^^^ | ^^^^^
@ -19,7 +19,7 @@ LL | ready(()).await;
= help: to override `-D warnings` add `#[allow(clippy::unused_async)]` = help: to override `-D warnings` add `#[allow(clippy::unused_async)]`
error: unused `async` for function with no await statements error: unused `async` for function with no await statements
--> $DIR/unused_async.rs:46:5 --> $DIR/unused_async.rs:45:5
| |
LL | async fn f3() {} LL | async fn f3() {}
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@ -27,7 +27,7 @@ LL | async fn f3() {}
= help: consider removing the `async` from this function = help: consider removing the `async` from this function
error: unused `async` for function with no await statements error: unused `async` for function with no await statements
--> $DIR/unused_async.rs:59:1 --> $DIR/unused_async.rs:58:1
| |
LL | / async fn foo() -> i32 { LL | / async fn foo() -> i32 {
LL | | LL | |
@ -38,7 +38,7 @@ LL | | }
= help: consider removing the `async` from this function = help: consider removing the `async` from this function
error: unused `async` for function with no await statements error: unused `async` for function with no await statements
--> $DIR/unused_async.rs:71:5 --> $DIR/unused_async.rs:70:5
| |
LL | / async fn unused(&self) -> i32 { LL | / async fn unused(&self) -> i32 {
LL | | LL | |