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..f9ace7e25d1b3 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::AMBIGUOUS_DERIVE_HELPERS; + 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( + AMBIGUOUS_DERIVE_HELPERS, + AttributeLintKind::AmbiguousDeriveHelpers, + ident.span, + ); + } attributes.push(ident.name); } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 867b937d4090d..805cdf126d970 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -1,6 +1,9 @@ lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition .suggestion = use `crate` +lint_ambiguous_derive_helpers = + there exists a built-in attribute with the same name + lint_ambiguous_glob_reexport = ambiguous glob re-exports .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 377b3c439453e..ac918a12c0020 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::AmbiguousDeriveHelpers => { + lints::AmbiguousDeriveHelpers.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 a20d90e1227e9..8791bfca1f2ae 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3225,6 +3225,10 @@ pub(crate) struct DocAliasDuplicated { #[diag(lint_doc_auto_cfg_expects_hide_or_show)] pub(crate) struct DocAutoCfgExpectsHideOrShow; +#[derive(LintDiagnostic)] +#[diag(lint_ambiguous_derive_helpers)] +pub(crate) struct AmbiguousDeriveHelpers; + #[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 ff108031badc1..21fdde1997a2e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -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, @@ -4237,6 +4238,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 + /// = 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 diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4c78287b7784f..869966de54f15 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, + AmbiguousDeriveHelpers, DocUnknownInclude { span: Span, inner: &'static str, diff --git a/tests/ui/attributes/ambiguous_derive_helpers.rs b/tests/ui/attributes/ambiguous_derive_helpers.rs new file mode 100644 index 0000000000000..684e9a8cc0ba6 --- /dev/null +++ b/tests/ui/attributes/ambiguous_derive_helpers.rs @@ -0,0 +1,12 @@ +#![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() +} diff --git a/tests/ui/attributes/ambiguous_derive_helpers.stderr b/tests/ui/attributes/ambiguous_derive_helpers.stderr new file mode 100644 index 0000000000000..788ac32f34029 --- /dev/null +++ b/tests/ui/attributes/ambiguous_derive_helpers.stderr @@ -0,0 +1,16 @@ +error: there exists a built-in attribute with the same name + --> $DIR/ambiguous_derive_helpers.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/ambiguous_derive_helpers.rs:2:9 + | +LL | #![deny(ambiguous_derive_helpers)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +