diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index e315d6abea395..f2a4fe96a362a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -14,8 +14,8 @@ use super::prelude::{ALL_TARGETS, AllowedTargets}; use super::{AcceptMapping, AttributeParser, template}; use crate::context::{AcceptContext, FinalizeContext}; use crate::diagnostics::{ - AttrCrateLevelOnly, DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, - DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, + DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, + DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues, DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocKeywordNotKeyword, DocTestLiteral, @@ -26,6 +26,7 @@ use crate::diagnostics::{ use crate::parser::{ ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser, }; +use crate::target_checking::Policy::Allow; fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> bool { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we @@ -63,15 +64,6 @@ fn check_attr_not_crate_level( true } -/// Checks that an attribute is used at the crate level. Returns `true` if valid. -fn check_attr_crate_level(cx: &mut AcceptContext<'_, '_>, span: Span) -> bool { - if cx.shared.target != Target::Crate { - cx.emit_lint(INVALID_DOC_ATTRIBUTES, AttrCrateLevelOnly, span); - return false; - } - true -} - // FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`. fn expected_name_value(cx: &mut AcceptContext<'_, '_>, span: Span, _name: Option) { cx.emit_lint(INVALID_DOC_ATTRIBUTES, ExpectedNameValue, span); @@ -163,9 +155,10 @@ impl DocParser { return; } - if !check_attr_crate_level(cx, path.span()) { - return; - } + cx.check_target( + sym::no_crate_inject.as_str(), + &AllowedTargets::AllowList(&[Allow(Target::Crate)]), + ); self.attribute.no_crate_inject = Some(path.span()) } @@ -530,9 +523,10 @@ impl DocParser { return; } let span = path.span(); - if !check_attr_crate_level(cx, span) { - return; - } + cx.check_target( + concat!("(", stringify!($ident), ")"), + &AllowedTargets::AllowList(&[Allow(Target::Crate)]), + ); self.attribute.$ident = Some(span); }}; } @@ -548,9 +542,7 @@ impl DocParser { return; }; - if !check_attr_crate_level(cx, path.span()) { - return; - } + cx.check_target(s.as_str(), &AllowedTargets::AllowList(&[Allow(Target::Crate)])); // FIXME: It's errorring when the attribute is passed multiple times on the command // line. diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index a37d56419adac..ec67fdad6410b 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -286,13 +286,6 @@ pub(crate) struct DocTestUnknown { #[diag("`#![doc(test(...)]` does not take a literal")] pub(crate) struct DocTestLiteral; -#[derive(Diagnostic)] -#[diag("this attribute can only be applied at the crate level")] -#[note( - "read for more information" -)] -pub(crate) struct AttrCrateLevelOnly; - #[derive(Diagnostic)] #[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; diff --git a/tests/ui/attributes/doc-crate-level.rs b/tests/ui/attributes/doc-crate-level.rs new file mode 100644 index 0000000000000..1acd8c46d35ad --- /dev/null +++ b/tests/ui/attributes/doc-crate-level.rs @@ -0,0 +1,21 @@ +#![feature(rustdoc_internals)] + +#[doc(rust_logo)] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(html_favicon_url = "example.org")] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(html_logo_url = "example.org")] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(html_playground_url = "example.org")] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(issue_tracker_base_url = "example.org")] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(html_root_url = "example.org")] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(html_no_source)] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +#[doc(test(no_crate_inject))] +//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` +fn function() {} + +fn main() {} diff --git a/tests/ui/attributes/doc-crate-level.stderr b/tests/ui/attributes/doc-crate-level.stderr new file mode 100644 index 0000000000000..b44d9c39b613a --- /dev/null +++ b/tests/ui/attributes/doc-crate-level.stderr @@ -0,0 +1,98 @@ +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:3:1 + | +LL | #[doc(rust_logo)] + | ^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:5:1 + | +LL | #[doc(html_favicon_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:7:1 + | +LL | #[doc(html_logo_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:9:1 + | +LL | #[doc(html_playground_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:11:1 + | +LL | #[doc(issue_tracker_base_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:13:1 + | +LL | #[doc(html_root_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:15:1 + | +LL | #[doc(html_no_source)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![doc]` + --> $DIR/doc-crate-level.rs:17:1 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/doc-crate-level.rs:19:1 + | +LL | fn function() {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/feature-gates/doc-rust-logo.rs b/tests/ui/feature-gates/doc-rust-logo.rs index 08857cc778f5b..2ad7272ceafe0 100644 --- a/tests/ui/feature-gates/doc-rust-logo.rs +++ b/tests/ui/feature-gates/doc-rust-logo.rs @@ -2,6 +2,4 @@ //~^ ERROR this subset of the `doc` attribute is meant for internal use only //! This is not an official rust crate -#[doc(rust_logo)] -//~^ 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..a89bd2c17ed38 100644 --- a/tests/ui/feature-gates/doc-rust-logo.stderr +++ b/tests/ui/feature-gates/doc-rust-logo.stderr @@ -9,15 +9,6 @@ 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 -warning: this attribute can only be applied at the crate level - --> $DIR/doc-rust-logo.rs:5:7 - | -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 1 previous error For more information about this error, try `rustc --explain E0658`.