From e54078b38e6b5a3c9e6a1e72a14d2c9a4bfeeda4 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 3 Oct 2026 15:31:28 +0200 Subject: [PATCH 1/2] reserve unknown doc attributes --- .../rustc_attr_parsing/src/attributes/doc.rs | 47 ++++++++++++------- .../rustc_attr_parsing/src/diagnostics.rs | 8 ++++ tests/rustdoc-ui/lints/doc-attr-2.rs | 9 ++-- tests/rustdoc-ui/lints/doc-attr-2.stderr | 22 ++++----- tests/ui/attributes/doc-attr.rs | 8 ++-- tests/ui/attributes/doc-attr.stderr | 39 ++++++++------- tests/ui/repr/invalid_repr_list_help.rs | 2 +- tests/ui/repr/invalid_repr_list_help.stderr | 8 +--- tests/ui/rustdoc/deny-invalid-doc-attrs.rs | 4 +- .../ui/rustdoc/deny-invalid-doc-attrs.stderr | 10 +--- tests/ui/rustdoc/doc-primitive.rs | 2 +- tests/ui/rustdoc/doc-primitive.stderr | 8 +--- 12 files changed, 80 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 7aeedc1493027..e1c4e7e13f016 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -18,9 +18,9 @@ use crate::diagnostics::{ DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues, - DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocKeywordNotKeyword, DocTestLiteral, - DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude, DocUnknownPasses, - DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, + DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocKeywordNotKeyword, DocReserved, + DocTestLiteral, DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude, + DocUnknownPasses, DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, IllFormedAttributeInput, MalformedDoc, UnusedDuplicate, }; use crate::parser::{ @@ -666,18 +666,30 @@ impl DocParser { let span = path.span(); cx.emit_lint(INVALID_DOC_ATTRIBUTES, DocUnknownSpotlight { sugg_span: span }, span); } - Some(sym::include) if let Some(nv) = args.as_name_value() => { - let inner = match cx.attr_style { - AttrStyle::Outer => "", - AttrStyle::Inner => "!", - }; - let value = nv.value_as_lit().symbol; - let span = path.span(); - cx.emit_lint( - INVALID_DOC_ATTRIBUTES, - DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) }, - span, - ); + Some(sym::include) => { + if let Some(nv) = args.as_name_value() { + let inner = match cx.attr_style { + AttrStyle::Outer => "", + AttrStyle::Inner => "!", + }; + let value = nv.value_as_lit().symbol; + let span = path.span(); + cx.emit_lint( + INVALID_DOC_ATTRIBUTES, + DocUnknownInclude { + inner, + value, + sugg: (span, Applicability::MaybeIncorrect), + }, + span, + ); + } else { + cx.emit_lint( + INVALID_DOC_ATTRIBUTES, + DocUnknownAny { name: sym::include }, + path.span(), + ); + } } Some(name @ (sym::passes | sym::no_default_passes)) => { let span = path.span(); @@ -692,13 +704,14 @@ impl DocParser { cx.emit_lint(INVALID_DOC_ATTRIBUTES, DocUnknownPlugins { label_span: span }, span); } Some(name) => { - cx.emit_lint(INVALID_DOC_ATTRIBUTES, DocUnknownAny { name }, path.span()); + cx.emit_err(DocReserved { name, span: path.span() }); } None => { let full_name = path.segments().map(|s| s.as_str()).intersperse("::").collect::(); let name = Symbol::intern(&full_name); - cx.emit_lint(INVALID_DOC_ATTRIBUTES, DocUnknownAny { name }, path.span()); + + cx.emit_err(DocReserved { name, span: path.span() }); } } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index df426cb5e19f5..1b2c25344cea4 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -263,6 +263,14 @@ pub(crate) struct DocUnknownAny { pub name: Symbol, } +#[derive(Diagnostic)] +#[diag("reserved `doc` attribute `{$name}`")] +pub(crate) struct DocReserved { + pub name: Symbol, + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("expected boolean for `#[doc(auto_cfg = ...)]`")] pub(crate) struct DocAutoCfgWrongLiteral; diff --git a/tests/rustdoc-ui/lints/doc-attr-2.rs b/tests/rustdoc-ui/lints/doc-attr-2.rs index 9802fb5d95a5c..adf69e81f4a18 100644 --- a/tests/rustdoc-ui/lints/doc-attr-2.rs +++ b/tests/rustdoc-ui/lints/doc-attr-2.rs @@ -1,12 +1,11 @@ -#![deny(invalid_doc_attributes)] #![doc(as_ptr)] -//~^ ERROR unknown `doc` attribute `as_ptr` +//~^ ERROR reserved `doc` attribute `as_ptr` #[doc(as_ptr)] -//~^ ERROR unknown `doc` attribute `as_ptr` +//~^ ERROR reserved `doc` attribute `as_ptr` pub fn foo() {} #[doc(foo::bar, crate::bar::baz = "bye")] -//~^ ERROR unknown `doc` attribute `foo::bar` -//~| ERROR unknown `doc` attribute `crate::bar::baz` +//~^ ERROR reserved `doc` attribute `foo::bar` +//~| ERROR reserved `doc` attribute `crate::bar::baz` fn bar() {} diff --git a/tests/rustdoc-ui/lints/doc-attr-2.stderr b/tests/rustdoc-ui/lints/doc-attr-2.stderr index 7c10f7b546612..ae90b83100fa0 100644 --- a/tests/rustdoc-ui/lints/doc-attr-2.stderr +++ b/tests/rustdoc-ui/lints/doc-attr-2.stderr @@ -1,29 +1,23 @@ -error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr-2.rs:2:8 +error: reserved `doc` attribute `as_ptr` + --> $DIR/doc-attr-2.rs:1:8 | LL | #![doc(as_ptr)] | ^^^^^^ - | -note: the lint level is defined here - --> $DIR/doc-attr-2.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ -error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr-2.rs:5:7 +error: reserved `doc` attribute `as_ptr` + --> $DIR/doc-attr-2.rs:4:7 | LL | #[doc(as_ptr)] | ^^^^^^ -error: unknown `doc` attribute `foo::bar` - --> $DIR/doc-attr-2.rs:9:7 +error: reserved `doc` attribute `foo::bar` + --> $DIR/doc-attr-2.rs:8:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^ -error: unknown `doc` attribute `crate::bar::baz` - --> $DIR/doc-attr-2.rs:9:17 +error: reserved `doc` attribute `crate::bar::baz` + --> $DIR/doc-attr-2.rs:8:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/doc-attr.rs b/tests/ui/attributes/doc-attr.rs index 8c81bc18d6aec..0c212e833e2c9 100644 --- a/tests/ui/attributes/doc-attr.rs +++ b/tests/ui/attributes/doc-attr.rs @@ -1,10 +1,10 @@ #![deny(invalid_doc_attributes)] #![crate_type = "lib"] #![doc(as_ptr)] -//~^ ERROR unknown `doc` attribute +//~^ ERROR reserved `doc` attribute #[doc(as_ptr)] -//~^ ERROR unknown `doc` attribute +//~^ ERROR reserved `doc` attribute pub fn foo() {} #[doc(123)] @@ -16,6 +16,6 @@ pub fn foo() {} //~| WARN //~| WARN #[doc(foo::bar, crate::bar::baz = "bye")] -//~^ ERROR unknown `doc` attribute -//~| ERROR unknown `doc` attribute +//~^ ERROR reserved `doc` attribute +//~| ERROR reserved `doc` attribute fn bar() {} diff --git a/tests/ui/attributes/doc-attr.stderr b/tests/ui/attributes/doc-attr.stderr index 4dc096d87cb40..3dbd2bf79d186 100644 --- a/tests/ui/attributes/doc-attr.stderr +++ b/tests/ui/attributes/doc-attr.stderr @@ -1,21 +1,27 @@ -error: unknown `doc` attribute `as_ptr` +error: reserved `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | LL | #![doc(as_ptr)] | ^^^^^^ - | -note: the lint level is defined here - --> $DIR/doc-attr.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ -error: unknown `doc` attribute `as_ptr` +error: reserved `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:6:7 | LL | #[doc(as_ptr)] | ^^^^^^ +error: reserved `doc` attribute `foo::bar` + --> $DIR/doc-attr.rs:18:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + +error: reserved `doc` attribute `crate::bar::baz` + --> $DIR/doc-attr.rs:18:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^ + error: expected this to be of the form `... = "..."` --> $DIR/doc-attr.rs:10:7 | @@ -23,6 +29,11 @@ LL | #[doc(123)] | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/doc-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: expected this to be of the form `... = "..."` --> $DIR/doc-attr.rs:13:7 @@ -40,17 +51,5 @@ LL | #[doc("hello", "bar")] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: unknown `doc` attribute `foo::bar` - --> $DIR/doc-attr.rs:18:7 - | -LL | #[doc(foo::bar, crate::bar::baz = "bye")] - | ^^^^^^^^ - -error: unknown `doc` attribute `crate::bar::baz` - --> $DIR/doc-attr.rs:18:17 - | -LL | #[doc(foo::bar, crate::bar::baz = "bye")] - | ^^^^^^^^^^^^^^^ - error: aborting due to 7 previous errors diff --git a/tests/ui/repr/invalid_repr_list_help.rs b/tests/ui/repr/invalid_repr_list_help.rs index 407514d014d8a..930ec0d334128 100644 --- a/tests/ui/repr/invalid_repr_list_help.rs +++ b/tests/ui/repr/invalid_repr_list_help.rs @@ -18,5 +18,5 @@ pub enum OwO4 { } #[repr(uwu)] //~ERROR: malformed `repr` attribute input -#[doc(owo)] //~ERROR: unknown `doc` attribute +#[doc(owo)] //~ERROR: reserved `doc` attribute pub struct Owo5; diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 17e6e99c82f4f..7265602ed9a89 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -48,17 +48,11 @@ LL | #[repr(uwu)] | = note: for more information, visit -error: unknown `doc` attribute `owo` +error: reserved `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:21:7 | LL | #[doc(owo)] | ^^^ - | -note: the lint level is defined here - --> $DIR/invalid_repr_list_help.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/rustdoc/deny-invalid-doc-attrs.rs b/tests/ui/rustdoc/deny-invalid-doc-attrs.rs index 15bfd723424e2..5ae438db6e376 100644 --- a/tests/ui/rustdoc/deny-invalid-doc-attrs.rs +++ b/tests/ui/rustdoc/deny-invalid-doc-attrs.rs @@ -1,5 +1,3 @@ -#![deny(invalid_doc_attributes)] -//~^ NOTE defined here #![doc(x)] -//~^ ERROR unknown `doc` attribute `x` +//~^ ERROR reserved `doc` attribute `x` fn main() {} diff --git a/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr index 0884e9c8bb2e7..15fbffe4a28d8 100644 --- a/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr +++ b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr @@ -1,14 +1,8 @@ -error: unknown `doc` attribute `x` - --> $DIR/deny-invalid-doc-attrs.rs:3:8 +error: reserved `doc` attribute `x` + --> $DIR/deny-invalid-doc-attrs.rs:1:8 | LL | #![doc(x)] | ^ - | -note: the lint level is defined here - --> $DIR/deny-invalid-doc-attrs.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-primitive.rs b/tests/ui/rustdoc/doc-primitive.rs index fbb1e1bc1fa23..64348f932f27a 100644 --- a/tests/ui/rustdoc/doc-primitive.rs +++ b/tests/ui/rustdoc/doc-primitive.rs @@ -1,7 +1,7 @@ #![deny(invalid_doc_attributes)] #[doc(primitive = "foo")] -//~^ ERROR unknown `doc` attribute `primitive` +//~^ ERROR reserved `doc` attribute `primitive` mod bar {} fn main() {} diff --git a/tests/ui/rustdoc/doc-primitive.stderr b/tests/ui/rustdoc/doc-primitive.stderr index 4ba310ca24101..d9cb5405360f0 100644 --- a/tests/ui/rustdoc/doc-primitive.stderr +++ b/tests/ui/rustdoc/doc-primitive.stderr @@ -1,14 +1,8 @@ -error: unknown `doc` attribute `primitive` +error: reserved `doc` attribute `primitive` --> $DIR/doc-primitive.rs:3:7 | LL | #[doc(primitive = "foo")] | ^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/doc-primitive.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From f4acea6b5ace1cd012fa4570bd573762316318cf Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 3 Oct 2026 20:22:55 +0200 Subject: [PATCH 2/2] Fix rust_logo feature gate --- compiler/rustc_attr_parsing/src/attributes/doc.rs | 12 +++++------- tests/ui/feature-gates/doc-rust-logo.rs | 3 ++- tests/ui/feature-gates/doc-rust-logo.stderr | 13 ++++++++++++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index e1c4e7e13f016..cc56ddc69e79e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -625,13 +625,11 @@ impl DocParser { no_args_and_not_crate_level!(search_unbox) } Some(sym::rust_logo) => { - // FIXME: Only feature gated at the crate level (!!) - if cx.target == Target::Crate { - gated!( - rustdoc_internals, - "the `#[doc(rust_logo)]` attribute is used for Rust branding" - ); - } + gated!( + rustdoc_internals, + "the `#[doc(rust_logo)]` attribute is used for Rust branding" + ); + no_args_and_crate_level!(rust_logo) } Some(sym::auto_cfg) => { diff --git a/tests/ui/feature-gates/doc-rust-logo.rs b/tests/ui/feature-gates/doc-rust-logo.rs index 08857cc778f5b..d3a0f5a8c8830 100644 --- a/tests/ui/feature-gates/doc-rust-logo.rs +++ b/tests/ui/feature-gates/doc-rust-logo.rs @@ -3,5 +3,6 @@ //! This is not an official rust crate #[doc(rust_logo)] -//~^ WARN this attribute can only be applied at the crate level +//~^ ERROR this subset of the `doc` attribute is meant for internal use only +//~| WARN this attribute can only be applied at the crate level fn main() {} diff --git a/tests/ui/feature-gates/doc-rust-logo.stderr b/tests/ui/feature-gates/doc-rust-logo.stderr index f31837be284d1..95092944de5c0 100644 --- a/tests/ui/feature-gates/doc-rust-logo.stderr +++ b/tests/ui/feature-gates/doc-rust-logo.stderr @@ -9,6 +9,17 @@ LL | #![doc(rust_logo)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: the `#[doc(rust_logo)]` attribute is used for Rust branding +error[E0658]: this subset of the `doc` attribute is meant for internal use only + --> $DIR/doc-rust-logo.rs:5:7 + | +LL | #[doc(rust_logo)] + | ^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `#[doc(rust_logo)]` attribute is used for Rust branding + warning: this attribute can only be applied at the crate level --> $DIR/doc-rust-logo.rs:5:7 | @@ -18,6 +29,6 @@ LL | #[doc(rust_logo)] = note: read for more information = note: `#[warn(invalid_doc_attributes)]` on by default -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0658`.