Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@

pub use rustc_ast_ir::visit::VisitorResult;
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
use rustc_macros::StableHash;
use rustc_span::{Ident, Span, Spanned, Symbol};
use thin_vec::ThinVec;

use crate::ast::*;
use crate::tokenstream::DelimSpan;

#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, StableHash)]
pub enum AssocCtxt {
Trait,
Impl { of_trait: bool },
Expand Down
44 changes: 22 additions & 22 deletions compiler/rustc_attr_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_span::def_id::DefId;
use rustc_span::{Symbol, kw, sym};

use crate::PrintAttribute;
use crate::target::{MethodKind, Target};
use crate::target::{AssocCtxt, MethodKind, Target};

/// All of the lang items, defined or not.
/// Defined lang items can come from the current crate or its dependencies.
Expand Down Expand Up @@ -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(AssocCtxt::Trait), GenericRequirement::Exact(0);
SizeOf, sym::mem_size_const, size_const, Target::AssocConst(AssocCtxt::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;
Expand All @@ -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(AssocCtxt::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(AssocCtxt::Trait), GenericRequirement::None;
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;

Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
Expand Down Expand Up @@ -237,9 +237,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(AssocCtxt::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(AssocCtxt::Trait), GenericRequirement::None;
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;

Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
Expand All @@ -249,24 +249,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(AssocCtxt::Trait), GenericRequirement::Exact(1);
CallOnceFuture, sym::call_once_future, call_once_future, Target::AssocTy(AssocCtxt::Trait), GenericRequirement::Exact(1);
CallRefFuture, sym::call_ref_future, call_ref_future, Target::AssocTy(AssocCtxt::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(AssocCtxt::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(AssocCtxt::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(AssocCtxt::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(AssocCtxt::Trait), GenericRequirement::Exact(1);
CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy(AssocCtxt::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;
Expand Down Expand Up @@ -384,8 +384,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(AssocCtxt::Impl { of_trait: false }), GenericRequirement::Exact(1);
AsyncGenFinished, sym::AsyncGenFinished, async_gen_finished, Target::AssocConst(AssocCtxt::Impl { of_trait: false }), GenericRequirement::Exact(1);

// FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually.
Expand Down Expand Up @@ -421,8 +421,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(AssocCtxt::Trait), GenericRequirement::Exact(0);
RangeMin, sym::RangeMin, range_min, Target::AssocConst(AssocCtxt::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`
Expand Down Expand Up @@ -453,9 +453,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(AssocCtxt::Trait), GenericRequirement::Exact(0);
FieldType, sym::field_type, field_type, Target::AssocTy(AssocCtxt::Trait), GenericRequirement::Exact(0);
FieldOffset, sym::field_offset, field_offset, Target::AssocConst(AssocCtxt::Trait), GenericRequirement::Exact(0);

// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_attr_ir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::fmt::{self, Display};

use rustc_ast::visit::AssocCtxt;
pub use rustc_ast::visit::AssocCtxt;
use rustc_ast::{AssocItemKind, ForeignItemKind, ast};
use rustc_macros::StableHash;

Expand Down Expand Up @@ -49,9 +49,9 @@ pub enum Target {
Expression,
Statement,
Arm,
AssocConst,
AssocConst(AssocCtxt),
Method(MethodKind),
AssocTy,
AssocTy(AssocCtxt),
ForeignFn,
ForeignStatic,
ForeignTy,
Expand Down Expand Up @@ -81,7 +81,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
Expand Down Expand Up @@ -157,7 +157,7 @@ impl Target {

pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target {
match kind {
AssocItemKind::Const(_) => Target::AssocConst,
AssocItemKind::Const(_) => Target::AssocConst(assoc_ctxt),
AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt {
AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() },
AssocCtxt::Impl { of_trait, .. } => {
Expand All @@ -168,7 +168,7 @@ impl Target {
}
}
}),
AssocItemKind::Type(_) => Target::AssocTy,
AssocItemKind::Type(_) => Target::AssocTy(assoc_ctxt),
AssocItemKind::Delegation(_) => Target::Delegation { mac: false },
AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true },
AssocItemKind::MacCall(_) => Target::MacroCall,
Expand Down Expand Up @@ -210,14 +210,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",
Expand Down Expand Up @@ -265,14 +265,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",
Expand Down
31 changes: 28 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use rustc_ast::LitKind;
use rustc_attr_ir::{DeprecatedSince, Deprecation, RustcVersion, VERSION_PLACEHOLDER};
use rustc_feature::AttributeStability;
use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;

use super::prelude::*;
use super::util::parse_version;
use crate::diagnostics::{DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince};
use crate::diagnostics::{
DeprecatedAnnotationHasNoEffect, DeprecatedItemSuggestion, InvalidSince, MissingNote,
MissingSince,
};
use crate::target_checking::Policy::AllowSilent;

fn get(
cx: &mut AcceptContext<'_, '_>,
Expand Down Expand Up @@ -48,8 +53,12 @@ impl SingleAttributeParser for DeprecatedParser {
Allow(Target::ForeignTy),
Allow(Target::Field),
Allow(Target::Trait),
Allow(Target::AssocTy),
Allow(Target::AssocConst),
Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
Allow(Target::AssocConst(AssocCtxt::Trait)),
AllowSilent(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),
Allow(Target::AssocTy(AssocCtxt::Trait)),
AllowSilent(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
Allow(Target::Variant),
Allow(Target::Impl { of_trait: false }),
Allow(Target::Crate),
Expand Down Expand Up @@ -182,6 +191,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(AssocCtxt::Impl { of_trait: true })
| Target::AssocTy(AssocCtxt::Impl { of_trait: true })
) {
let attr_span = cx.attr_span;
cx.emit_lint(
UNUSED_ATTRIBUTES,
DeprecatedAnnotationHasNoEffect { span: attr_span },

@JonathanBrouwer JonathanBrouwer Aug 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be its own diagnostic rather than just the default Policy::Warn diagnostic?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using UNUSED_ATTRIBUTES is better here because it's indicates that the attribute "has no effect" rather than saying it has a "wrong target" which is a better fit for unused attributes and unused lint group.

@JonathanBrouwer JonathanBrouwer Aug 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this path covered by any tests?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here in tests/ui/deprecation/deprecation-sanity.rs:

#[deprecated = "hello"] //~ ERROR attribute cannot be used on
//~| WARN previously accepted
impl Default for X {
    fn default() -> Self {
        X
    }
}

attr_span,
);
}

Some(AttributeKind::Deprecated {
deprecation: Deprecation { since, note, suggestion },
span: cx.attr_span,
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,12 +820,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(AssocCtxt::Impl { of_trait: false })),
// Allow(Target::AssocConst(AssocCtxt::Trait)),
// Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
// 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(AssocCtxt::Impl { of_trait: false })),
// Allow(Target::AssocTy(AssocCtxt::Trait)),
// Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),
// Allow(Target::ForeignFn),
// Allow(Target::ForeignStatic),
// Allow(Target::ForeignTy),
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ impl SingleAttributeParser for InlineParser {
Warn(Target::Field),
Warn(Target::MacroDef),
Warn(Target::Arm),
Warn(Target::AssocConst),
Warn(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),
Warn(Target::AssocConst(AssocCtxt::Trait)),
Warn(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),
Warn(Target::MacroCall),
]);
const TEMPLATE: AttributeTemplate = template!(
Expand Down
Loading
Loading