From aaa1340da48dddb97fa116af7028d0decab5cfd5 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Mon, 3 Aug 2026 21:50:11 +0300 Subject: [PATCH] Use attribute parser for `deprecated` attribute checking --- .../src/attributes/deprecation.rs | 29 +++++++++- .../rustc_attr_parsing/src/attributes/doc.rs | 8 ++- .../src/attributes/inline.rs | 4 +- .../src/attributes/link_attrs.rs | 4 +- .../src/attributes/prelude.rs | 2 +- .../src/attributes/rustc_dump.rs | 33 ++++++++--- .../src/attributes/rustc_internal.rs | 40 +++++++++---- .../src/attributes/stability.rs | 14 +++-- .../src/session_diagnostics.rs | 11 ++++ .../rustc_attr_parsing/src/target_checking.rs | 10 +++- compiler/rustc_hir/src/lang_items.rs | 44 +++++++------- compiler/rustc_hir/src/lib.rs | 2 +- compiler/rustc_hir/src/target.rs | 38 +++++++++---- compiler/rustc_passes/src/check_attr.rs | 57 ++++++++++--------- compiler/rustc_passes/src/diagnostics.rs | 11 ---- 15 files changed, 200 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 46f99691b602d..ef28a054e46bd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -2,12 +2,15 @@ use rustc_ast::LitKind; use rustc_feature::AttributeStability; use rustc_hir::VERSION_PLACEHOLDER; use rustc_hir::attrs::{DeprecatedSince, Deprecation, RustcVersion}; +use rustc_session::lint::builtin::UNUSED_ATTRIBUTES; use super::prelude::*; use super::util::parse_version; use crate::session_diagnostics::{ - DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince, + DeprecatedAnnotationHasNoEffect, DeprecatedItemSuggestion, InvalidSince, MissingNote, + MissingSince, }; +use crate::target_checking::Policy::AllowSilent; fn get( cx: &mut AcceptContext<'_, '_>, @@ -51,8 +54,12 @@ impl SingleAttributeParser for DeprecatedParser { Allow(Target::ForeignTy), Allow(Target::Field), Allow(Target::Trait), - Allow(Target::AssocTy), - Allow(Target::AssocConst), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + AllowSilent(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + AllowSilent(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Variant), Allow(Target::Impl { of_trait: false }), Allow(Target::Crate), @@ -185,6 +192,22 @@ impl SingleAttributeParser for DeprecatedParser { return None; } + // `#[deprecated]` on trait-impl associated items has no effect (deprecation comes from the + // trait definition). Methods also get `useless_deprecated` from target checking. + if matches!( + cx.target, + Target::Method(MethodKind::TraitImpl) + | Target::AssocConst(AssocKind::TraitImpl) + | Target::AssocTy(AssocKind::TraitImpl) + ) { + let attr_span = cx.attr_span; + cx.emit_lint( + UNUSED_ATTRIBUTES, + DeprecatedAnnotationHasNoEffect { span: attr_span }, + attr_span, + ); + } + Some(AttributeKind::Deprecated { deprecation: Deprecation { since, note, suggestion }, span: cx.attr_span, diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index cba00f5f068a6..da5e62df2c345 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -822,12 +822,16 @@ impl AttributeParser for DocParser { // Allow(Target::TraitAlias), // Allow(Target::Impl { of_trait: true }), // Allow(Target::Impl { of_trait: false }), - // Allow(Target::AssocConst), + // Allow(Target::AssocConst(AssocKind::Inherent)), + // Allow(Target::AssocConst(AssocKind::Trait)), + // Allow(Target::AssocConst(AssocKind::TraitImpl)), // Allow(Target::Method(MethodKind::Inherent)), // Allow(Target::Method(MethodKind::Trait { body: true })), // Allow(Target::Method(MethodKind::Trait { body: false })), // Allow(Target::Method(MethodKind::TraitImpl)), - // Allow(Target::AssocTy), + // Allow(Target::AssocTy(AssocKind::Inherent)), + // Allow(Target::AssocTy(AssocKind::Trait)), + // Allow(Target::AssocTy(AssocKind::TraitImpl)), // Allow(Target::ForeignFn), // Allow(Target::ForeignStatic), // Allow(Target::ForeignTy), diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 52960ae220a59..4492d24692084 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -23,7 +23,9 @@ impl SingleAttributeParser for InlineParser { Warn(Target::Field), Warn(Target::MacroDef), Warn(Target::Arm), - Warn(Target::AssocConst), + Warn(Target::AssocConst(AssocKind::Inherent)), + Warn(Target::AssocConst(AssocKind::Trait)), + Warn(Target::AssocConst(AssocKind::TraitImpl)), Warn(Target::MacroCall), ]); const TEMPLATE: AttributeTemplate = template!( diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 935265924d7da..c3ae3adea7b72 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -547,7 +547,9 @@ impl NoArgsAttributeParser for ExportStableParser { Allow(Target::Enum), Allow(Target::Union), Allow(Target::TyAlias), - Allow(Target::AssocTy), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Use), Allow(Target::Mod), Allow(Target::Impl { of_trait: false }), diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs index 744d5368580d8..cf7471ceb760d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs @@ -2,7 +2,7 @@ #[doc(hidden)] pub(super) use rustc_hir::attrs::AttributeKind; #[doc(hidden)] -pub(super) use rustc_hir::{MethodKind, Target}; +pub(super) use rustc_hir::{AssocKind, MethodKind, Target}; #[doc(hidden)] pub(super) use rustc_span::{Ident, Span, Symbol, sym}; #[doc(hidden)] diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index e20d4585925c3..e13f6f2940322 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -1,6 +1,6 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::{AttributeKind, RustcDumpLayoutKind}; -use rustc_hir::{MethodKind, Target}; +use rustc_hir::{AssocKind, MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use super::prelude::*; @@ -59,8 +59,12 @@ impl NoArgsAttributeParser for RustcDumpGenericsParser { Allow(Target::Closure), Allow(Target::TyAlias), Allow(Target::Const), - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Impl { of_trait: false }), Allow(Target::Impl { of_trait: true }), Allow(Target::Method(MethodKind::Inherent)), @@ -101,8 +105,11 @@ pub(crate) struct RustcDumpItemBoundsParser; impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; - const ALLOWED_TARGETS: AllowedTargets<'_> = - AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), + ]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } @@ -176,8 +183,12 @@ pub(crate) struct RustcDumpObjectLifetimeDefaultsParser; impl NoArgsAttributeParser for RustcDumpObjectLifetimeDefaultsParser { const PATH: &[Symbol] = &[sym::rustc_dump_object_lifetime_defaults]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Const), Allow(Target::Enum), Allow(Target::Fn), @@ -203,8 +214,12 @@ pub(crate) struct RustcDumpPredicatesParser; impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Const), Allow(Target::Delegation { mac: false }), Allow(Target::Delegation { mac: true }), diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index de4f9f63a51fe..2fc35f5f6a557 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -764,8 +764,12 @@ impl CombineAttributeParser for RustcCleanParser { const CONVERT: ConvertFn = |items, _| AttributeKind::RustcClean(items); const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Const), Allow(Target::Enum), Allow(Target::Expression), @@ -857,8 +861,12 @@ impl SingleAttributeParser for RustcIfThisChangedParser { const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Const), Allow(Target::Enum), Allow(Target::Expression), @@ -915,8 +923,12 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { |items, _span| AttributeKind::RustcThenThisWouldNeed(items); const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Const), Allow(Target::Enum), Allow(Target::Expression), @@ -991,12 +1003,16 @@ impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { Allow(Target::TraitAlias), Allow(Target::Impl { of_trait: false }), Allow(Target::Impl { of_trait: true }), - Allow(Target::AssocConst), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), - Allow(Target::AssocTy), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::ForeignFn), Allow(Target::ForeignStatic), Allow(Target::ForeignTy), @@ -1018,8 +1034,12 @@ impl SingleAttributeParser for RustcDiagnosticItemParser { Allow(Target::Enum), Allow(Target::MacroDef), Allow(Target::TyAlias), - Allow(Target::AssocTy), - Allow(Target::AssocConst), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Fn), Allow(Target::Const), Allow(Target::Mod), diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 62f16d9719d23..be4792646618d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -5,7 +5,7 @@ use rustc_feature::{ACCEPTED_LANG_FEATURES, AttributeStability}; use rustc_hir::attrs::UnstableRemovedFeature; use rustc_hir::target::GenericParamKind; use rustc_hir::{ - DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel, + AssocKind, DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel, StableSince, Target, UnstableReason, VERSION_PLACEHOLDER, }; @@ -29,8 +29,12 @@ const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Mod), Allow(Target::Use), // FIXME I don't think this does anything? Allow(Target::Const), - Allow(Target::AssocConst), - Allow(Target::AssocTy), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::Trait), Allow(Target::TraitAlias), Allow(Target::TyAlias), @@ -243,7 +247,9 @@ impl AttributeParser for ConstStabilityParser { Allow(Target::Impl { of_trait: true }), Allow(Target::Use), // FIXME I don't think this does anything? Allow(Target::Const), - Allow(Target::AssocConst), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), Allow(Target::Trait), Allow(Target::Static), Allow(Target::Crate), diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index b7c7b39bcb48b..97a66f32489c3 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -29,6 +29,17 @@ pub(crate) struct BothFfiConstAndPure { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag("this `#[deprecated]` annotation has no effect")] +pub(crate) struct DeprecatedAnnotationHasNoEffect { + #[suggestion( + "remove the unnecessary deprecation attribute", + applicability = "machine-applicable", + code = "" + )] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("attribute should be applied to `#[repr(transparent)]` types")] pub(crate) struct RustcPubTransparent { diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 6b0d1b094ca0f..8f039aa282468 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -4,7 +4,7 @@ use rustc_ast::{AttrStyle, Safety}; use rustc_errors::{DiagArgValue, MultiSpan, StashKey}; use rustc_feature::Features; use rustc_hir::attrs::AttributeKind; -use rustc_hir::{AttrItem, Attribute, MethodKind, Target}; +use rustc_hir::{AssocKind, AttrItem, Attribute, MethodKind, Target}; use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym}; use crate::context::AcceptContext; @@ -507,12 +507,16 @@ pub(crate) const ALL_TARGETS: &[Policy] = { Allow(Target::Expression), Allow(Target::Statement), Allow(Target::Arm), - Allow(Target::AssocConst), + Allow(Target::AssocConst(AssocKind::Inherent)), + Allow(Target::AssocConst(AssocKind::Trait)), + Allow(Target::AssocConst(AssocKind::TraitImpl)), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), - Allow(Target::AssocTy), + Allow(Target::AssocTy(AssocKind::Inherent)), + Allow(Target::AssocTy(AssocKind::Trait)), + Allow(Target::AssocTy(AssocKind::TraitImpl)), Allow(Target::ForeignFn), Allow(Target::ForeignStatic), Allow(Target::ForeignTy), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e6e0b3726552f..e94fb9af262c0 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -14,7 +14,7 @@ use rustc_span::{Symbol, kw, sym}; use crate::attrs::PrintAttribute; use crate::def_id::DefId; -use crate::{MethodKind, Target}; +use crate::{AssocKind, MethodKind, Target}; /// All of the lang items, defined or not. /// Defined lang items can come from the current crate or its dependencies. @@ -161,8 +161,8 @@ language_item_table! { MetaSized, sym::meta_sized, meta_sized_trait, Target::Trait, GenericRequirement::Exact(0); PointeeSized, sym::pointee_sized, pointee_sized_trait, Target::Trait, GenericRequirement::Exact(0); Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); - AlignOf, sym::mem_align_const, align_const, Target::AssocConst, GenericRequirement::Exact(0); - SizeOf, sym::mem_size_const, size_const, Target::AssocConst, GenericRequirement::Exact(0); + AlignOf, sym::mem_align_const, align_const, Target::AssocConst(AssocKind::Trait), GenericRequirement::Exact(0); + SizeOf, sym::mem_size_const, size_const, Target::AssocConst(AssocKind::Trait), GenericRequirement::Exact(0); OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; @@ -174,10 +174,10 @@ language_item_table! { Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0); DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None; /// The associated item of the `DiscriminantKind` trait. - Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None; + Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy(AssocKind::Trait), GenericRequirement::None; PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None; - Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None; + Metadata, sym::metadata_type, metadata_type, Target::AssocTy(AssocKind::Trait), GenericRequirement::None; DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None; Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0); @@ -235,9 +235,9 @@ language_item_table! { Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); - DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; + DerefTarget, sym::deref_target, deref_target, Target::AssocTy(AssocKind::Trait), GenericRequirement::None; Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; - ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None; + ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy(AssocKind::Trait), GenericRequirement::None; LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None; Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); @@ -247,24 +247,24 @@ language_item_table! { AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); - AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output, Target::AssocTy, GenericRequirement::Exact(1); - CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy, GenericRequirement::Exact(1); - CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy, GenericRequirement::Exact(2); + AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(1); + CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(1); + CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(2); AsyncFnKindHelper, sym::async_fn_kind_helper, async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); - AsyncFnKindUpvars, sym::async_fn_kind_upvars, async_fn_kind_upvars, Target::AssocTy, GenericRequirement::Exact(5); + AsyncFnKindUpvars, sym::async_fn_kind_upvars, async_fn_kind_upvars, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(5); - FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; + FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy(AssocKind::Trait), GenericRequirement::None; Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0); FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0); Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); - FutureOutput, sym::future_output, future_output, Target::AssocTy, GenericRequirement::Exact(0); + FutureOutput, sym::future_output, future_output, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(0); AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0); CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None; Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Exact(1); - CoroutineReturn, sym::coroutine_return, coroutine_return, Target::AssocTy, GenericRequirement::Exact(1); - CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy, GenericRequirement::Exact(1); + CoroutineReturn, sym::coroutine_return, coroutine_return, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(1); + CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(1); CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; @@ -381,8 +381,8 @@ language_item_table! { PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None; AsyncGenReady, sym::AsyncGenReady, async_gen_ready, Target::Method(MethodKind::Inherent), GenericRequirement::Exact(1); - AsyncGenPending, sym::AsyncGenPending, async_gen_pending, Target::AssocConst, GenericRequirement::Exact(1); - AsyncGenFinished, sym::AsyncGenFinished, async_gen_finished, Target::AssocConst, GenericRequirement::Exact(1); + AsyncGenPending, sym::AsyncGenPending, async_gen_pending, Target::AssocConst(AssocKind::Inherent), GenericRequirement::Exact(1); + AsyncGenFinished, sym::AsyncGenFinished, async_gen_finished, Target::AssocConst(AssocKind::Inherent), GenericRequirement::Exact(1); // FIXME(swatinem): the following lang items are used for async lowering and // should become obsolete eventually. @@ -418,8 +418,8 @@ language_item_table! { Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None; RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None; RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None; - RangeMax, sym::RangeMax, range_max, Target::AssocConst, GenericRequirement::Exact(0); - RangeMin, sym::RangeMin, range_min, Target::AssocConst, GenericRequirement::Exact(0); + RangeMax, sym::RangeMax, range_max, Target::AssocConst(AssocKind::Trait), GenericRequirement::Exact(0); + RangeMin, sym::RangeMin, range_min, Target::AssocConst(AssocKind::Trait), GenericRequirement::Exact(0); RangeSub, sym::RangeSub, range_sub, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); // `new_range` types that are `Copy + IntoIterator` @@ -450,9 +450,9 @@ language_item_table! { // Field representing types. FieldRepresentingType, sym::field_representing_type, field_representing_type, Target::Struct, GenericRequirement::Exact(3); Field, sym::field, field, Target::Trait, GenericRequirement::Exact(0); - FieldBase, sym::field_base, field_base, Target::AssocTy, GenericRequirement::Exact(0); - FieldType, sym::field_type, field_type, Target::AssocTy, GenericRequirement::Exact(0); - FieldOffset, sym::field_offset, field_offset, Target::AssocConst, GenericRequirement::Exact(0); + FieldBase, sym::field_base, field_base, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(0); + FieldType, sym::field_type, field_type, Target::AssocTy(AssocKind::Trait), GenericRequirement::Exact(0); + FieldOffset, sym::field_offset, field_offset, Target::AssocConst(AssocKind::Trait), GenericRequirement::Exact(0); // Used to fallback `{float}` to `f32` when `f32: From<{float}>` From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1); diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 761fc680d2ff6..66edfa7d6ee51 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -40,6 +40,6 @@ pub use lang_items::{LangItem, LanguageItems}; pub use rustc_hir_id::*; pub use rustc_span::def_id; pub use stability::*; -pub use target::{MethodKind, Target}; +pub use target::{AssocKind, MethodKind, Target}; pub use crate::arena::Arena; diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 2097e860468ec..7d1c74a7f11a8 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -29,6 +29,17 @@ pub enum MethodKind { Inherent, } +/// Context of an associated const or associated type (not methods; see [`MethodKind`]). +#[derive(Copy, Clone, PartialEq, Debug, Eq, StableHash)] +pub enum AssocKind { + /// Associated item in a `trait Trait` block + Trait, + /// Associated item in a `impl Trait for Type` block + TraitImpl, + /// Associated item in a `impl Type` block + Inherent, +} + #[derive(Copy, Clone, PartialEq, Debug, Eq, StableHash)] pub enum Target { ExternCrate, @@ -52,9 +63,9 @@ pub enum Target { Expression, Statement, Arm, - AssocConst, + AssocConst(AssocKind), Method(MethodKind), - AssocTy, + AssocTy(AssocKind), ForeignFn, ForeignStatic, ForeignTy, @@ -84,7 +95,7 @@ rustc_error_messages::into_diag_arg_using_display!(Target); impl Target { pub fn is_associated_item(self) -> bool { match self { - Target::AssocConst | Target::AssocTy | Target::Method(_) => true, + Target::AssocConst(_) | Target::AssocTy(_) | Target::Method(_) => true, Target::ExternCrate | Target::Use | Target::Static @@ -159,8 +170,13 @@ impl Target { } pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target { + let assoc_kind = match assoc_ctxt { + AssocCtxt::Trait => AssocKind::Trait, + AssocCtxt::Impl { of_trait: true, .. } => AssocKind::TraitImpl, + AssocCtxt::Impl { of_trait: false, .. } => AssocKind::Inherent, + }; match kind { - AssocItemKind::Const(_) => Target::AssocConst, + AssocItemKind::Const(_) => Target::AssocConst(assoc_kind), AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt { AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() }, AssocCtxt::Impl { of_trait, .. } => { @@ -171,7 +187,7 @@ impl Target { } } }), - AssocItemKind::Type(_) => Target::AssocTy, + AssocItemKind::Type(_) => Target::AssocTy(assoc_kind), AssocItemKind::Delegation(_) => Target::Delegation { mac: false }, AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true }, AssocItemKind::MacCall(_) => Target::MacroCall, @@ -213,14 +229,14 @@ impl Target { Target::Expression => "expression", Target::Statement => "statement", Target::Arm => "match arm", - Target::AssocConst => "associated const", + Target::AssocConst(_) => "associated const", Target::Method(kind) => match kind { MethodKind::Inherent => "inherent method", MethodKind::Trait { body: false } => "required trait method", MethodKind::Trait { body: true } => "provided trait method", MethodKind::TraitImpl => "trait method in an impl block", }, - Target::AssocTy => "associated type", + Target::AssocTy(_) => "associated type", Target::ForeignFn => "foreign function", Target::ForeignStatic => "foreign static item", Target::ForeignTy => "foreign type", @@ -268,14 +284,14 @@ impl Target { Target::Expression => "expressions", Target::Statement => "statements", Target::Arm => "match arms", - Target::AssocConst => "associated consts", + Target::AssocConst(_) => "associated consts", Target::Method(kind) => match kind { MethodKind::Inherent => "inherent methods", MethodKind::Trait { body: false } => "required trait methods", MethodKind::Trait { body: true } => "provided trait methods", MethodKind::TraitImpl => "trait methods in impl blocks", }, - Target::AssocTy => "associated types", + Target::AssocTy(_) => "associated types", Target::ForeignFn => "foreign functions", Target::ForeignStatic => "foreign statics", Target::ForeignTy => "foreign types", @@ -331,14 +347,14 @@ impl From<&hir::GenericParam<'_>> for Target { impl From<&hir::TraitItem<'_>> for Target { fn from(trait_item: &hir::TraitItem<'_>) -> Target { match trait_item.kind { - TraitItemKind::Const(..) => Target::AssocConst, + TraitItemKind::Const(..) => Target::AssocConst(AssocKind::Trait), TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { Target::Method(MethodKind::Trait { body: false }) } TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { Target::Method(MethodKind::Trait { body: true }) } - TraitItemKind::Type(..) => Target::AssocTy, + TraitItemKind::Type(..) => Target::AssocTy(AssocKind::Trait), } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6489167afcdac..bc0b16ef13d3c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -24,7 +24,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, + self as hir, AssocKind, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, GenericParamKind, HirId, Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, find_attr, }; @@ -62,7 +62,15 @@ struct DiagnosticOnConstOnlyForNonConstTraitImpls { fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target { match impl_item.kind { - hir::ImplItemKind::Const(..) => Target::AssocConst, + hir::ImplItemKind::Const(..) => { + let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id; + let containing_item = tcx.hir_expect_item(parent_def_id); + let of_trait = match &containing_item.kind { + hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), + _ => bug!("parent of an ImplItem must be an Impl"), + }; + Target::AssocConst(if of_trait { AssocKind::TraitImpl } else { AssocKind::Inherent }) + } hir::ImplItemKind::Fn(..) => { let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id; let containing_item = tcx.hir_expect_item(parent_def_id); @@ -71,12 +79,20 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) _ => bug!("parent of an ImplItem must be an Impl"), }; if containing_impl_is_for_trait { - Target::Method(MethodKind::Trait { body: true }) + Target::Method(MethodKind::TraitImpl) } else { Target::Method(MethodKind::Inherent) } } - hir::ImplItemKind::Type(..) => Target::AssocTy, + hir::ImplItemKind::Type(..) => { + let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id; + let containing_item = tcx.hir_expect_item(parent_def_id); + let of_trait = match &containing_item.kind { + hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), + _ => bug!("parent of an ImplItem must be an Impl"), + }; + Target::AssocTy(if of_trait { AssocKind::TraitImpl } else { AssocKind::Inherent }) + } } } @@ -192,9 +208,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcAllowConstFnUnstable(_, first_span) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } - AttributeKind::Deprecated { span: attr_span, .. } => { - self.check_deprecated(hir_id, *attr_span, target) - } AttributeKind::RustcDumpObjectLifetimeDefaults => { self.check_dump_object_lifetime_defaults(hir_id); } @@ -250,6 +263,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::CustomMir(..) => (), AttributeKind::DebuggerVisualizer(..) => (), AttributeKind::DefaultLibAllocator => (), + AttributeKind::Deprecated { .. } => (), AttributeKind::DoNotRecommend => (), // `#[doc]` is actually a lot more than just doc comments, so is checked below AttributeKind::DocComment { .. } => (), @@ -703,7 +717,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Fn | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { + | Target::Method( + MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, + ) => { // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported. if let Some(did) = hir_id.as_owner() && self.tcx.def_kind(did).has_codegen_attrs() @@ -729,7 +745,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_naked(&self, hir_id: HirId, target: Target) { match target { Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { + | Target::Method( + MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, + ) => { let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); let abi = fn_sig.header.abi; if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() { @@ -795,7 +813,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) { if let Some(location) = match target { - Target::AssocTy => { + Target::AssocTy(_) => { if let DefKind::Impl { .. } = self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)) { @@ -804,7 +822,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { None } } - Target::AssocConst => { + Target::AssocConst(_) => { let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id; let containing_item = self.tcx.hir_expect_item(parent_def_id); // We can't link to trait impl's consts. @@ -1272,23 +1290,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_deprecated(&self, hir_id: HirId, attr_span: Span, target: Target) { - match target { - Target::AssocConst | Target::Method(..) | Target::AssocTy - if self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)) - == DefKind::Impl { of_trait: true } => - { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - diagnostics::DeprecatedAnnotationHasNoEffect { span: attr_span }, - ); - } - _ => {} - } - } - fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) { if target != Target::MacroDef { return; diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index e1650eecb8f4d..726630c2d498a 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -289,17 +289,6 @@ pub(crate) struct InvalidMayDangle { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag("this `#[deprecated]` annotation has no effect")] -pub(crate) struct DeprecatedAnnotationHasNoEffect { - #[suggestion( - "remove the unnecessary deprecation attribute", - applicability = "machine-applicable", - code = "" - )] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("`#[panic_handler]` function required, but not found")] pub(crate) struct MissingPanicHandler;