diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 402232a1720b7..89b27d8936410 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -309,6 +309,7 @@ symbols! { RwLockReadGuard, RwLockWriteGuard, Saturating, + SeekFrom, Send, SeqCst, Sized, diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 644b294db8da1..2a4262b236780 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2058,6 +2058,7 @@ pub trait Seek { /// It is used by the [`Seek`] trait. #[derive(Copy, PartialEq, Eq, Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "SeekFrom")] pub enum SeekFrom { /// Sets the offset to the provided number of bytes. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs index e45c7962f13f4..8bc535ac47a84 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs @@ -8,7 +8,7 @@ use rustc_span::sym; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::implements_trait; -use clippy_utils::{match_def_path, paths}; +use clippy_utils::is_enum_variant_ctor; use super::SEEK_FROM_CURRENT; @@ -36,8 +36,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { if let ExprKind::Call(f, args) = expr.kind && let ExprKind::Path(ref path) = f.kind - && let Some(def_id) = cx.qpath_res(path, f.hir_id).opt_def_id() - && match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT) + && let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id() + && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id) { // check if argument of `SeekFrom::Current` is `0` if args.len() == 1 diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs index cc4cb47e35c63..7c09cc252e13a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; -use clippy_utils::{is_expr_used_or_unified, match_def_path, paths}; +use clippy_utils::{is_expr_used_or_unified, is_enum_variant_ctor}; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; @@ -28,8 +28,8 @@ pub(super) fn check<'tcx>( && implements_trait(cx, ty, seek_trait_id, &[]) && let ExprKind::Call(func, args1) = arg.kind && let ExprKind::Path(ref path) = func.kind - && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() - && match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START) + && let Some(ctor_call_id) = cx.qpath_res(path, func.hir_id).opt_def_id() + && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Start), ctor_call_id) && args1.len() == 1 && let ExprKind::Lit(lit) = args1[0].kind && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 5db14872c36b0..0d0d6219c5e05 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -263,24 +263,18 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> } } -pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool { - if let Res::Def(DefKind::Ctor(..), id) = res - && let Some(id) = cx.tcx.opt_parent(id) - { - cx.tcx.is_diagnostic_item(diag_item, id) - } else { - false - } -} -/// Checks if a `QPath` resolves to a constructor of a diagnostic item. -pub fn is_diagnostic_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, diagnostic_item: Symbol) -> bool { - if let QPath::Resolved(_, path) = qpath { - if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res { - return cx.tcx.is_diagnostic_item(diagnostic_item, cx.tcx.parent(ctor_id)); - } - } - false +/// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`. +pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool { + let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else { + return false; + }; + + let variants = cx.tcx.adt_def(enum_def_id).variants().iter(); + variants + .filter(|variant| variant.name == variant_name) + .filter_map(|variant| variant.ctor.as_ref()) + .any(|(_, ctor_def_id)| *ctor_def_id == ctor_call_id) } /// Checks if the `DefId` matches the given diagnostic item or it's constructor. diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index c8b59fca52418..a30edc48fff26 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -29,8 +29,7 @@ pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; // Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items. -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"]; +// ... none currently! // Paths in clippy itself pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];