diff options
| author | Urgau <urgau@numericable.fr> | 2025-05-01 17:24:00 +0200 |
|---|---|---|
| committer | Urgau <urgau@numericable.fr> | 2025-05-22 19:12:13 +0200 |
| commit | 80c6a0885079038caa0bc90670afbf5ead806c17 (patch) | |
| tree | e6f8b221de6b4ac0673c3bd453c91f468beabd8e | |
| parent | eec894d3f9bf708d8c4c0679bc57ed899d6c37ab (diff) | |
| download | rust-80c6a0885079038caa0bc90670afbf5ead806c17.tar.gz rust-80c6a0885079038caa0bc90670afbf5ead806c17.zip | |
Allow `#![doc(test(attr(..)))]` at module level too
| -rw-r--r-- | compiler/rustc_passes/messages.ftl | 5 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 12 | ||||
| -rw-r--r-- | src/doc/rustdoc/src/write-documentation/the-doc-attribute.md | 19 | ||||
| -rw-r--r-- | tests/rustdoc-ui/lints/invalid-doc-attr.rs | 4 | ||||
| -rw-r--r-- | tests/rustdoc-ui/lints/invalid-doc-attr.stderr | 32 | ||||
| -rw-r--r-- | tests/ui/rustdoc/doc-test-attr-pass.rs | 4 |
7 files changed, 107 insertions, 20 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6d815e510ea..2f264ed4fc0 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -46,6 +46,11 @@ passes_attr_crate_level = .suggestion = to apply to the crate, use an inner attribute .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information +passes_attr_mod_level = + this attribute can only be applied at module level + .suggestion = to apply to the crate, use an inner attribute at the crate level + .note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information + passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5c0d0cf4796..376b424a1af 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1252,7 +1252,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let bang_span = attr.span().lo() + BytePos(1); let sugg = (attr.style() == AttrStyle::Outer && self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID) - .then_some(errors::AttrCrateLevelOnlySugg { + .then_some(errors::AttrCrateLevelSugg { attr: attr.span().with_lo(bang_span).with_hi(bang_span), }); self.tcx.emit_node_span_lint( @@ -1266,13 +1266,50 @@ impl<'tcx> CheckAttrVisitor<'tcx> { true } - /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if - /// valid. - fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) { + /// Checks that an attribute is used at module level. Returns `true` if valid. + fn check_attr_mod_level( + &self, + attr: &Attribute, + meta: &MetaItemInner, + hir_id: HirId, + target: Target, + ) -> bool { + if target != Target::Mod { + // insert a bang between `#` and `[...` + let bang_span = attr.span().lo() + BytePos(1); + let sugg = (attr.style() == AttrStyle::Outer + && self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID) + .then_some(errors::AttrCrateLevelSugg { + attr: attr.span().with_lo(bang_span).with_hi(bang_span), + }); + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + errors::AttrModLevelOnly { sugg }, + ); + return false; + } + true + } + + /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place. + fn check_test_attr( + &self, + attr: &Attribute, + meta: &MetaItemInner, + hir_id: HirId, + target: Target, + ) { if let Some(metas) = meta.meta_item_list() { for i_meta in metas { match (i_meta.name(), i_meta.meta_item()) { - (Some(sym::attr | sym::no_crate_inject), _) => {} + (Some(sym::attr), _) => { + self.check_attr_mod_level(attr, meta, hir_id, target); + } + (Some(sym::no_crate_inject), _) => { + self.check_attr_crate_level(attr, meta, hir_id); + } (_, Some(m)) => { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, @@ -1359,9 +1396,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } Some(sym::test) => { - if self.check_attr_crate_level(attr, meta, hir_id) { - self.check_test_attr(meta, hir_id); - } + self.check_test_attr(attr, meta, hir_id, target); } Some( diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 00682a9c7a7..38b0db37e12 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1890,12 +1890,20 @@ pub(crate) struct UnusedVarTryIgnoreSugg { #[note] pub(crate) struct AttrCrateLevelOnly { #[subdiagnostic] - pub sugg: Option<AttrCrateLevelOnlySugg>, + pub sugg: Option<AttrCrateLevelSugg>, +} + +#[derive(LintDiagnostic)] +#[diag(passes_attr_mod_level)] +#[note] +pub(crate) struct AttrModLevelOnly { + #[subdiagnostic] + pub sugg: Option<AttrCrateLevelSugg>, } #[derive(Subdiagnostic)] #[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")] -pub(crate) struct AttrCrateLevelOnlySugg { +pub(crate) struct AttrCrateLevelSugg { #[primary_span] pub attr: Span, } diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index 45146993371..afbcf4000c5 100644 --- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -141,6 +141,11 @@ But if you include this: it will not. +## At the module level + +These forms of the `#[doc]` attribute are used on individual modules, to control how +they are documented. + ### `test(attr(...))` This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For @@ -148,6 +153,20 @@ example, if you want your doctests to fail if they have dead code, you could add ```rust,no_run #![doc(test(attr(deny(dead_code))))] + +mod my_mod { + #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module +} +``` + +`test(attr(..))` attributes are appended to the parent module's, they do not replace the current +list of attributes. In the previous example, both attributes would be present: + +```rust,no_run +// For every doctest in `my_mod` + +#![deny(dead_code)] // from the crate-root +#![allow(dead_code)] // from `my_mod` ``` ## At the item level diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs index e1cc08ca242..cd5ae44b126 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs @@ -4,6 +4,10 @@ #![doc(masked)] //~^ ERROR this attribute can only be applied to an `extern crate` item +#[doc(test(attr(allow(warnings))))] +//~^ ERROR can only be applied at module level +//~| HELP to apply to the crate, use an inner attribute +//~| SUGGESTION ! #[doc(test(no_crate_inject))] //~^ ERROR can only be applied at the crate level //~| HELP to apply to the crate, use an inner attribute diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr index 7621999a8ca..0fd55ff94d8 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr @@ -1,18 +1,30 @@ -error: this attribute can only be applied at the crate level +error: this attribute can only be applied at module level --> $DIR/invalid-doc-attr.rs:7:7 | +LL | #[doc(test(attr(allow(warnings))))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information + = note: `#[deny(invalid_doc_attributes)]` on by default +help: to apply to the crate, use an inner attribute at the crate level + | +LL | #![doc(test(attr(allow(warnings))))] + | + + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:11:7 + | 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: `#[deny(invalid_doc_attributes)]` on by default help: to apply to the crate, use an inner attribute | LL | #![doc(test(no_crate_inject))] | + error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:11:7 + --> $DIR/invalid-doc-attr.rs:15:7 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -23,7 +35,7 @@ LL | pub fn foo() {} = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:16:12 + --> $DIR/invalid-doc-attr.rs:20:12 | LL | #![doc(test(no_crate_inject))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +43,7 @@ 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 error: conflicting doc inlining attributes - --> $DIR/invalid-doc-attr.rs:26:7 + --> $DIR/invalid-doc-attr.rs:30:7 | LL | #[doc(inline)] | ^^^^^^ this attribute... @@ -41,7 +53,7 @@ LL | #[doc(no_inline)] = help: remove one of the conflicting attributes error: this attribute can only be applied to an `extern crate` item - --> $DIR/invalid-doc-attr.rs:32:7 + --> $DIR/invalid-doc-attr.rs:36:7 | LL | #[doc(masked)] | ^^^^^^ only applicable on `extern crate` items @@ -52,7 +64,7 @@ LL | pub struct Masked; = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information error: this attribute cannot be applied to an `extern crate self` item - --> $DIR/invalid-doc-attr.rs:36:7 + --> $DIR/invalid-doc-attr.rs:40:7 | LL | #[doc(masked)] | ^^^^^^ not applicable on `extern crate self` items @@ -69,7 +81,7 @@ LL | #![doc(masked)] = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:19:11 + --> $DIR/invalid-doc-attr.rs:23:11 | LL | #[doc(test(no_crate_inject))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +89,7 @@ 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 error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:21:11 + --> $DIR/invalid-doc-attr.rs:25:11 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -87,5 +99,5 @@ LL | pub fn baz() {} | = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/rustdoc/doc-test-attr-pass.rs b/tests/ui/rustdoc/doc-test-attr-pass.rs index f0120b7c2d0..40ffd5b2572 100644 --- a/tests/ui/rustdoc/doc-test-attr-pass.rs +++ b/tests/ui/rustdoc/doc-test-attr-pass.rs @@ -6,4 +6,8 @@ #![doc(test(attr(deny(warnings))))] #![doc(test())] +mod test { + #![doc(test(attr(allow(warnings))))] +} + pub fn foo() {} |
