diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index 3674aa7124abb..5e04e487ebb89 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -1,3 +1,6 @@ +use rustc_hir::lints::AttributeLintKind; +use rustc_session::lint::builtin::DERIVE_HELPER_CLASHES_WITH_BUILTIN_ATTR; + use super::prelude::*; const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets = @@ -126,6 +129,13 @@ fn parse_derive_like( cx.expected_identifier(ident.span); return None; } + if rustc_feature::is_builtin_attr_name(ident.name) { + cx.emit_lint( + DERIVE_HELPER_CLASHES_WITH_BUILTIN_ATTR, + AttributeLintKind::DeriveHelperClashesWithBuiltinAttr, + ident.span, + ); + } attributes.push(ident.name); } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1160bd9ffa749..645153d84487e 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -232,6 +232,9 @@ lint_deprecated_where_clause_location = where clause not allowed here .suggestion_move_to_end = move it to the end of the type declaration .suggestion_remove_where = remove this `where` +lint_derive_helper_clashes_with_builtin_attr = + there exists a built-in attribute with the same name + lint_diag_out_of_impl = diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f622de7f84d93..5c5df61ee9dda 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -375,6 +375,10 @@ pub fn decorate_attribute_lint( lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag) } + &AttributeLintKind::DeriveHelperClashesWithBuiltinAttr => { + lints::DeriveHelperClashesWithBuiltinAttr.decorate_lint(diag) + } + &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag) } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fde9546bd1c75..164ea03d1f89e 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3223,6 +3223,10 @@ pub(crate) struct DocAliasDuplicated { #[diag(lint_doc_auto_cfg_expects_hide_or_show)] pub(crate) struct DocAutoCfgExpectsHideOrShow; +#[derive(LintDiagnostic)] +#[diag(lint_derive_helper_clashes_with_builtin_attr)] +pub(crate) struct DeriveHelperClashesWithBuiltinAttr; + #[derive(LintDiagnostic)] #[diag(lint_doc_auto_cfg_hide_show_unexpected_item)] pub(crate) struct DocAutoCfgHideShowUnexpectedItem { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 99cce0c44b86d..8d7122911c03a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -35,6 +35,7 @@ declare_lint_pass! { DEPRECATED_IN_FUTURE, DEPRECATED_SAFE_2024, DEPRECATED_WHERE_CLAUSE_LOCATION, + DERIVE_HELPER_CLASHES_WITH_BUILTIN_ATTR, DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, @@ -4237,6 +4238,75 @@ declare_lint! { }; } +declare_lint! { + /// The `derive_helper_clashes_with_builtin_attr` 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(derive_helper_clashes_with_builtin_attr)] + /// + /// 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 + /// = note: `#[deny(derive_helper_clashes_with_builtin_attr)]` (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 DERIVE_HELPER_CLASHES_WITH_BUILTIN_ATTR, + Warn, + "same as a built-in attribute", + @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 diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7b41cfbb43ef0..2d9b642132dfd 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -796,6 +796,7 @@ pub enum AttributeLintKind { attr_name: Symbol, }, DocInvalid, + DeriveHelperClashesWithBuiltinAttr, DocUnknownInclude { span: Span, inner: &'static str, diff --git a/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.rs b/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.rs new file mode 100644 index 0000000000000..8152b7dbf2e97 --- /dev/null +++ b/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.rs @@ -0,0 +1,12 @@ +#![crate_type = "proc-macro"] +#![deny(derive_helper_clashes_with_builtin_attr)] + +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() +} diff --git a/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.stderr b/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.stderr new file mode 100644 index 0000000000000..8fbc4a027f69c --- /dev/null +++ b/tests/ui/attributes/derive_helper_clashes_with_builtin_attr.stderr @@ -0,0 +1,16 @@ +error: there exists a built-in attribute with the same name + --> $DIR/derive_helper_clashes_with_builtin_attr.rs:8: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 +note: the lint level is defined here + --> $DIR/derive_helper_clashes_with_builtin_attr.rs:2:9 + | +LL | #![deny(derive_helper_clashes_with_builtin_attr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +