Rollup merge of #151152 - nik-contrib:helper_attr_builtin, r=chenyukang

Add FCW for derive helper attributes that will conflict with built-in attributes

Adds a future-compatibility-warning deny-by-default lint that helps catch invalid derive helper attribute names early.

This issues the lint, saying that `ignore` helper will clash with the built-in `ignore` attribute.

```rust
#![crate_type = "proc-macro"]
#![deny(ambiguous_derive_helpers)]
use proc_macro::TokenStream;

#[proc_macro_derive(Trait, attributes(ignore))]
pub fn example(input: TokenStream) -> TokenStream {
    TokenStream::new()
}
```

If you actually tried to use that `ignore` helper attribute, you won't be able to due to the ambiguity:

```rust
#[derive(Trait)]
struct Foo {
    #[ignore]
    field: (),
}
```

Produces:

```
error[E0659]: `ignore` is ambiguous
 --> src/lib.rs:5:7
  |
5 |     #[ignore]
  |       ^^^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `ignore` could refer to a built-in attribute
note: `ignore` could also refer to the derive helper attribute defined here
 --> src/lib.rs:3:10
  |
3 | #[derive(Trait)]
  |          ^^^^^
```
This commit is contained in:
Jacob Pratt 2026-02-12 00:41:06 -05:00 committed by GitHub
commit 2dba56033e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 120 additions and 0 deletions

View file

@ -1,3 +1,6 @@
use rustc_hir::lints::AttributeLintKind;
use rustc_session::lint::builtin::AMBIGUOUS_DERIVE_HELPERS;
use super::prelude::*;
const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets =
@ -126,6 +129,13 @@ fn parse_derive_like<S: Stage>(
cx.expected_identifier(ident.span);
return None;
}
if rustc_feature::is_builtin_attr_name(ident.name) {
cx.emit_lint(
AMBIGUOUS_DERIVE_HELPERS,
AttributeLintKind::AmbiguousDeriveHelpers,
ident.span,
);
}
attributes.push(ident.name);
}
}

View file

@ -383,6 +383,10 @@ pub fn decorate_attribute_lint(
lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag)
}
&AttributeLintKind::AmbiguousDeriveHelpers => {
lints::AmbiguousDeriveHelpers.decorate_lint(diag)
}
&AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => {
lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag)
}

View file

@ -3752,6 +3752,10 @@ pub(crate) struct DocAliasDuplicated {
#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")]
pub(crate) struct DocAutoCfgExpectsHideOrShow;
#[derive(LintDiagnostic)]
#[diag("there exists a built-in attribute with the same name")]
pub(crate) struct AmbiguousDeriveHelpers;
#[derive(LintDiagnostic)]
#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items")]
pub(crate) struct DocAutoCfgHideShowUnexpectedItem {

View file

@ -17,6 +17,7 @@ declare_lint_pass! {
AARCH64_SOFTFLOAT_NEON,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
AMBIGUOUS_ASSOCIATED_ITEMS,
AMBIGUOUS_DERIVE_HELPERS,
AMBIGUOUS_GLOB_IMPORTED_TRAITS,
AMBIGUOUS_GLOB_IMPORTS,
AMBIGUOUS_GLOB_REEXPORTS,
@ -4267,6 +4268,75 @@ declare_lint! {
};
}
declare_lint! {
/// The `ambiguous_derive_helpers` lint detects cases where a derive macro's helper attribute
/// is the same name as that of a built-in attribute.
///
/// ### Example
///
/// ```rust,ignore (proc-macro)
/// #![crate_type = "proc-macro"]
/// #![deny(ambiguous_derive_helpers)]
///
/// use proc_macro::TokenStream;
///
/// #[proc_macro_derive(Trait, attributes(ignore))]
/// pub fn example(input: TokenStream) -> TokenStream {
/// TokenStream::new()
/// }
/// ```
///
/// Produces:
///
/// ```text
/// warning: there exists a built-in attribute with the same name
/// --> file.rs:5:39
/// |
/// 5 | #[proc_macro_derive(Trait, attributes(ignore))]
/// | ^^^^^^
/// |
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
/// = note: for more information, see issue #151152 <https://github.com/rust-lang/rust/issues/151152>
/// = note: `#[deny(ambiguous_derive_helpers)]` (part of `#[deny(future_incompatible)]`) on by default
/// ```
///
/// ### Explanation
///
/// Attempting to use this helper attribute will throw an error:
///
/// ```rust,ignore (needs-dependency)
/// #[derive(Trait)]
/// struct Example {
/// #[ignore]
/// fields: ()
/// }
/// ```
///
/// Produces:
///
/// ```text
/// error[E0659]: `ignore` is ambiguous
/// --> src/lib.rs:5:7
/// |
/// 5 | #[ignore]
/// | ^^^^^^ ambiguous name
/// |
/// = note: ambiguous because of a name conflict with a builtin attribute
/// = note: `ignore` could refer to a built-in attribute
/// note: `ignore` could also refer to the derive helper attribute defined here
/// --> src/lib.rs:3:10
/// |
/// 3 | #[derive(Trait)]
/// | ^^^^^
/// ```
pub AMBIGUOUS_DERIVE_HELPERS,
Warn,
"detects derive helper attributes that are ambiguous with built-in attributes",
@future_incompatible = FutureIncompatibleInfo {
reason: fcw!(FutureReleaseError #151276),
};
}
declare_lint! {
/// The `private_interfaces` lint detects types in a primary interface of an item,
/// that are more private than the item itself. Primary interface of an item is all

View file

@ -800,6 +800,7 @@ pub enum AttributeLintKind {
attr_name: Symbol,
},
DocInvalid,
AmbiguousDeriveHelpers,
DocUnknownInclude {
span: Span,
inner: &'static str,

View file

@ -0,0 +1,15 @@
//@ force-host
//@ no-prefer-dynamic
#![crate_type = "proc-macro"]
#![deny(ambiguous_derive_helpers)]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Trait, attributes(ignore))] //~ ERROR there exists a built-in attribute with the same name
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
pub fn deriving(input: TokenStream) -> TokenStream {
TokenStream::new()
}

View file

@ -0,0 +1,16 @@
error: there exists a built-in attribute with the same name
--> $DIR/ambiguous_derive_helpers.rs:11:39
|
LL | #[proc_macro_derive(Trait, attributes(ignore))]
| ^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #151276 <https://github.com/rust-lang/rust/issues/151276>
note: the lint level is defined here
--> $DIR/ambiguous_derive_helpers.rs:5:9
|
LL | #![deny(ambiguous_derive_helpers)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error