Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, DocInlineConflict, DocInlineOnlyUse,
Expand All @@ -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
Expand Down Expand Up @@ -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<Symbol>) {
cx.emit_lint(INVALID_DOC_ATTRIBUTES, ExpectedNameValue, span);
Expand Down Expand Up @@ -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::AllowListWarnRest(&[Allow(Target::Crate)]),
);

self.attribute.no_crate_inject = Some(path.span())
}
Expand Down Expand Up @@ -552,9 +545,10 @@ impl DocParser {
return;
}
let span = path.span();
if !check_attr_crate_level(cx, span) {
return;
}
cx.check_target(
concat!("(", stringify!($ident), ")"),
&AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]),
);
self.attribute.$ident = Some(span);
}};
}
Expand All @@ -570,9 +564,10 @@ impl DocParser {
return;
};

if !check_attr_crate_level(cx, path.span()) {
return;
}
cx.check_target(
s.as_str(),
&AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]),
);

// FIXME: It's errorring when the attribute is passed multiple times on the command
// line.
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_attr_parsing/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information"
)]
pub(crate) struct AttrCrateLevelOnly;

#[derive(Diagnostic)]
#[diag("conflicting doc inlining attributes")]
#[help("remove one of the conflicting attributes")]
Expand All @@ -347,6 +340,13 @@ pub(crate) struct DocInlineOnlyUse {
pub item_span: Span,
}

#[derive(Diagnostic)]
#[diag("this attribute can only be applied at the crate level")]
#[note(
"read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information"
)]
pub(crate) struct AttrCrateLevelOnly;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect, this needs a primary span, otherwise if used as an error it won't have a span to point at and will be displayed like this:

error: this attribute can only be applied at the crate level
   |
   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

(Fixed in #164582)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, thanks!


#[derive(Diagnostic)]
#[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")]
pub(crate) struct DoNotRecommendDoesNotExpectArgs;
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_attr_ir::{AttrItem, Attribute, AttributeKind};
use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
use rustc_feature::Features;
use rustc_lint_defs::builtin::{
MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, USELESS_DEPRECATED,
INVALID_DOC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, USELESS_DEPRECATED,
};
use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym};

Expand Down Expand Up @@ -244,6 +244,16 @@ impl<'sess> AttributeParser<'sess> {
})
.unwrap_or_default();

if name == "doc" {
let diag = crate::diagnostics::AttrCrateLevelOnly;
if warn {
cx.emit_lint(INVALID_DOC_ATTRIBUTES, diag, attr_span);
} else {
cx.emit_err(diag);
}
return;
}

let diag = crate::diagnostics::InvalidAttrStyle {
name,
is_used_as_inner,
Expand Down
3 changes: 2 additions & 1 deletion tests/rustdoc-ui/lints/invalid-crate-level-lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

pub mod bar {
#![doc(test(no_crate_inject))]
//~^ ERROR can only be applied at the crate level
//~^ ERROR unused attribute
//~| WARN this was previously accepted by the compiler but is being phased out

#[doc(test(no_crate_inject))]
//~^ ERROR can only be applied at the crate level
Expand Down
19 changes: 12 additions & 7 deletions tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: this attribute can only be applied at the crate level
--> $DIR/invalid-crate-level-lint.rs:4:12
--> $DIR/invalid-crate-level-lint.rs:4:1
|
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
note: the lint level is defined here
Expand All @@ -11,19 +11,24 @@ note: the lint level is defined here
LL | #![deny(invalid_doc_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^

error: this attribute can only be applied at the crate level
error: unused attribute
--> $DIR/invalid-crate-level-lint.rs:8:17
|
LL | #![doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ help: remove this attribute
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
note: attribute also specified here
--> $DIR/invalid-crate-level-lint.rs:4:12
|
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: this attribute can only be applied at the crate level
--> $DIR/invalid-crate-level-lint.rs:11:16
--> $DIR/invalid-crate-level-lint.rs:12:5
|
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

Expand Down
22 changes: 22 additions & 0 deletions tests/ui/attributes/doc-crate-level.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@check-pass
#![feature(rustdoc_internals)]

#[doc(rust_logo)]
//~^ WARN this attribute can only be applied at the crate level
#[doc(html_favicon_url = "example.org")]
//~^ WARN this attribute can only be applied at the crate level
#[doc(html_logo_url = "example.org")]
//~^ WARN this attribute can only be applied at the crate level
#[doc(html_playground_url = "example.org")]
//~^ WARN this attribute can only be applied at the crate level
#[doc(issue_tracker_base_url = "example.org")]
//~^ WARN this attribute can only be applied at the crate level
#[doc(html_root_url = "example.org")]
//~^ WARN this attribute can only be applied at the crate level
#[doc(html_no_source)]
//~^ WARN this attribute can only be applied at the crate level
#[doc(test(no_crate_inject))]
//~^ WARN this attribute can only be applied at the crate level
fn function() {}

fn main() {}
67 changes: 67 additions & 0 deletions tests/ui/attributes/doc-crate-level.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:4:1
|
LL | #[doc(rust_logo)]
| ^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
= note: `#[warn(invalid_doc_attributes)]` on by default

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:6:1
|
LL | #[doc(html_favicon_url = "example.org")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:8:1
|
LL | #[doc(html_logo_url = "example.org")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:10:1
|
LL | #[doc(html_playground_url = "example.org")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:12:1
|
LL | #[doc(issue_tracker_base_url = "example.org")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:14:1
|
LL | #[doc(html_root_url = "example.org")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:16:1
|
LL | #[doc(html_no_source)]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: this attribute can only be applied at the crate level
--> $DIR/doc-crate-level.rs:18:1
|
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

warning: 8 warnings emitted

4 changes: 2 additions & 2 deletions tests/ui/feature-gates/doc-rust-logo.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ LL | #![doc(rust_logo)]
= 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
--> $DIR/doc-rust-logo.rs:5:1
|
LL | #[doc(rust_logo)]
| ^^^^^^^^^
| ^^^^^^^^^^^^^^^^^
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
= note: `#[warn(invalid_doc_attributes)]` on by default
Expand Down
Loading