Skip to content

Commit 2e946d4

Browse files
committed
Allow #![doc(test(attr(..)))] at every level
1 parent eb8cd61 commit 2e946d4

File tree

9 files changed

+147
-116
lines changed

9 files changed

+147
-116
lines changed

compiler/rustc_passes/messages.ftl

-5
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ passes_attr_crate_level =
4646
.suggestion = to apply to the crate, use an inner attribute
4747
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
4848
49-
passes_attr_mod_level =
50-
this attribute can only be applied at module level
51-
.suggestion = to apply to the crate, use an inner attribute at the crate level
52-
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information
53-
5449
passes_attr_only_in_functions =
5550
`{$attr}` attribute can only be used on functions
5651

compiler/rustc_passes/src/check_attr.rs

+4-37
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
12521252
let bang_span = attr.span().lo() + BytePos(1);
12531253
let sugg = (attr.style() == AttrStyle::Outer
12541254
&& self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID)
1255-
.then_some(errors::AttrCrateLevelSugg {
1255+
.then_some(errors::AttrCrateLevelOnlySugg {
12561256
attr: attr.span().with_lo(bang_span).with_hi(bang_span),
12571257
});
12581258
self.tcx.emit_node_span_lint(
@@ -1266,46 +1266,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
12661266
true
12671267
}
12681268

1269-
/// Checks that an attribute is used at module level. Returns `true` if valid.
1270-
fn check_attr_mod_level(
1271-
&self,
1272-
attr: &Attribute,
1273-
meta: &MetaItemInner,
1274-
hir_id: HirId,
1275-
target: Target,
1276-
) -> bool {
1277-
if target != Target::Mod {
1278-
// insert a bang between `#` and `[...`
1279-
let bang_span = attr.span().lo() + BytePos(1);
1280-
let sugg = (attr.style() == AttrStyle::Outer
1281-
&& self.tcx.hir_get_parent_item(hir_id) == CRATE_OWNER_ID)
1282-
.then_some(errors::AttrCrateLevelSugg {
1283-
attr: attr.span().with_lo(bang_span).with_hi(bang_span),
1284-
});
1285-
self.tcx.emit_node_span_lint(
1286-
INVALID_DOC_ATTRIBUTES,
1287-
hir_id,
1288-
meta.span(),
1289-
errors::AttrModLevelOnly { sugg },
1290-
);
1291-
return false;
1292-
}
1293-
true
1294-
}
1295-
12961269
/// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place.
1297-
fn check_test_attr(
1298-
&self,
1299-
attr: &Attribute,
1300-
meta: &MetaItemInner,
1301-
hir_id: HirId,
1302-
target: Target,
1303-
) {
1270+
fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) {
13041271
if let Some(metas) = meta.meta_item_list() {
13051272
for i_meta in metas {
13061273
match (i_meta.name(), i_meta.meta_item()) {
13071274
(Some(sym::attr), _) => {
1308-
self.check_attr_mod_level(attr, meta, hir_id, target);
1275+
// Allowed everywhere like `#[doc]`
13091276
}
13101277
(Some(sym::no_crate_inject), _) => {
13111278
self.check_attr_crate_level(attr, meta, hir_id);
@@ -1396,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
13961363
}
13971364

13981365
Some(sym::test) => {
1399-
self.check_test_attr(attr, meta, hir_id, target);
1366+
self.check_test_attr(attr, meta, hir_id);
14001367
}
14011368

14021369
Some(

compiler/rustc_passes/src/errors.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -1890,20 +1890,12 @@ pub(crate) struct UnusedVarTryIgnoreSugg {
18901890
#[note]
18911891
pub(crate) struct AttrCrateLevelOnly {
18921892
#[subdiagnostic]
1893-
pub sugg: Option<AttrCrateLevelSugg>,
1894-
}
1895-
1896-
#[derive(LintDiagnostic)]
1897-
#[diag(passes_attr_mod_level)]
1898-
#[note]
1899-
pub(crate) struct AttrModLevelOnly {
1900-
#[subdiagnostic]
1901-
pub sugg: Option<AttrCrateLevelSugg>,
1893+
pub sugg: Option<AttrCrateLevelOnlySugg>,
19021894
}
19031895

19041896
#[derive(Subdiagnostic)]
19051897
#[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")]
1906-
pub(crate) struct AttrCrateLevelSugg {
1898+
pub(crate) struct AttrCrateLevelOnlySugg {
19071899
#[primary_span]
19081900
pub attr: Span,
19091901
}

src/doc/rustdoc/src/write-documentation/the-doc-attribute.md

+23-28
Original file line numberDiff line numberDiff line change
@@ -141,34 +141,6 @@ But if you include this:
141141

142142
it will not.
143143

144-
## At the module level
145-
146-
These forms of the `#[doc]` attribute are used on individual modules, to control how
147-
they are documented.
148-
149-
### `test(attr(...))`
150-
151-
This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
152-
example, if you want your doctests to fail if they have dead code, you could add this:
153-
154-
```rust,no_run
155-
#![doc(test(attr(deny(dead_code))))]
156-
157-
mod my_mod {
158-
#![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
159-
}
160-
```
161-
162-
`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
163-
list of attributes. In the previous example, both attributes would be present:
164-
165-
```rust,no_run
166-
// For every doctest in `my_mod`
167-
168-
#![deny(dead_code)] // from the crate-root
169-
#![allow(dead_code)] // from `my_mod`
170-
```
171-
172144
## At the item level
173145

174146
These forms of the `#[doc]` attribute are used on individual items, to control how
@@ -300,3 +272,26 @@ To get around this limitation, we just add `#[doc(alias = "lib_name_do_something
300272
on the `do_something` method and then it's all good!
301273
Users can now look for `lib_name_do_something` in our crate directly and find
302274
`Obj::do_something`.
275+
276+
### `test(attr(...))`
277+
278+
This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
279+
example, if you want your doctests to fail if they have dead code, you could add this:
280+
281+
```rust,no_run
282+
#![doc(test(attr(deny(dead_code))))]
283+
284+
mod my_mod {
285+
#![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
286+
}
287+
```
288+
289+
`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
290+
list of attributes. In the previous example, both attributes would be present:
291+
292+
```rust,no_run
293+
// For every doctest in `my_mod`
294+
295+
#![deny(dead_code)] // from the crate-root
296+
#![allow(dead_code)] // from `my_mod`
297+
```

tests/rustdoc-ui/lints/invalid-doc-attr.rs

-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
#![doc(masked)]
55
//~^ ERROR this attribute can only be applied to an `extern crate` item
66

7-
#[doc(test(attr(allow(warnings))))]
8-
//~^ ERROR can only be applied at module level
9-
//~| HELP to apply to the crate, use an inner attribute
10-
//~| SUGGESTION !
117
#[doc(test(no_crate_inject))]
128
//~^ ERROR can only be applied at the crate level
139
//~| HELP to apply to the crate, use an inner attribute
+10-22
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,18 @@
1-
error: this attribute can only be applied at module level
2-
--> $DIR/invalid-doc-attr.rs:7:7
3-
|
4-
LL | #[doc(test(attr(allow(warnings))))]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-module-level> for more information
8-
= note: `#[deny(invalid_doc_attributes)]` on by default
9-
help: to apply to the crate, use an inner attribute at the crate level
10-
|
11-
LL | #![doc(test(attr(allow(warnings))))]
12-
| +
13-
141
error: this attribute can only be applied at the crate level
15-
--> $DIR/invalid-doc-attr.rs:11:7
2+
--> $DIR/invalid-doc-attr.rs:7:7
163
|
174
LL | #[doc(test(no_crate_inject))]
185
| ^^^^^^^^^^^^^^^^^^^^^
196
|
207
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
8+
= note: `#[deny(invalid_doc_attributes)]` on by default
219
help: to apply to the crate, use an inner attribute
2210
|
2311
LL | #![doc(test(no_crate_inject))]
2412
| +
2513

2614
error: this attribute can only be applied to a `use` item
27-
--> $DIR/invalid-doc-attr.rs:15:7
15+
--> $DIR/invalid-doc-attr.rs:11:7
2816
|
2917
LL | #[doc(inline)]
3018
| ^^^^^^ only applicable on `use` items
@@ -35,15 +23,15 @@ LL | pub fn foo() {}
3523
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
3624

3725
error: this attribute can only be applied at the crate level
38-
--> $DIR/invalid-doc-attr.rs:20:12
26+
--> $DIR/invalid-doc-attr.rs:16:12
3927
|
4028
LL | #![doc(test(no_crate_inject))]
4129
| ^^^^^^^^^^^^^^^^^^^^^
4230
|
4331
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
4432

4533
error: conflicting doc inlining attributes
46-
--> $DIR/invalid-doc-attr.rs:30:7
34+
--> $DIR/invalid-doc-attr.rs:26:7
4735
|
4836
LL | #[doc(inline)]
4937
| ^^^^^^ this attribute...
@@ -53,7 +41,7 @@ LL | #[doc(no_inline)]
5341
= help: remove one of the conflicting attributes
5442

5543
error: this attribute can only be applied to an `extern crate` item
56-
--> $DIR/invalid-doc-attr.rs:36:7
44+
--> $DIR/invalid-doc-attr.rs:32:7
5745
|
5846
LL | #[doc(masked)]
5947
| ^^^^^^ only applicable on `extern crate` items
@@ -64,7 +52,7 @@ LL | pub struct Masked;
6452
= note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
6553

6654
error: this attribute cannot be applied to an `extern crate self` item
67-
--> $DIR/invalid-doc-attr.rs:40:7
55+
--> $DIR/invalid-doc-attr.rs:36:7
6856
|
6957
LL | #[doc(masked)]
7058
| ^^^^^^ not applicable on `extern crate self` items
@@ -81,15 +69,15 @@ LL | #![doc(masked)]
8169
= note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
8270

8371
error: this attribute can only be applied at the crate level
84-
--> $DIR/invalid-doc-attr.rs:23:11
72+
--> $DIR/invalid-doc-attr.rs:19:11
8573
|
8674
LL | #[doc(test(no_crate_inject))]
8775
| ^^^^^^^^^^^^^^^^^^^^^
8876
|
8977
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
9078

9179
error: this attribute can only be applied to a `use` item
92-
--> $DIR/invalid-doc-attr.rs:25:11
80+
--> $DIR/invalid-doc-attr.rs:21:11
9381
|
9482
LL | #[doc(inline)]
9583
| ^^^^^^ only applicable on `use` items
@@ -99,5 +87,5 @@ LL | pub fn baz() {}
9987
|
10088
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
10189

102-
error: aborting due to 10 previous errors
90+
error: aborting due to 9 previous errors
10391

tests/ui/lint/unused/useless-comment.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ macro_rules! mac {
99
/// foo //~ ERROR unused doc comment
1010
mac!();
1111

12+
/// a //~ ERROR unused doc comment
13+
#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
14+
unsafe extern "C" { }
15+
1216
fn foo() {
1317
/// a //~ ERROR unused doc comment
18+
#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
1419
let x = 12;
1520

1621
/// multi-line //~ ERROR unused doc comment
@@ -19,6 +24,7 @@ fn foo() {
1924
match x {
2025
/// c //~ ERROR unused doc comment
2126
1 => {},
27+
#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
2228
_ => {}
2329
}
2430

@@ -32,6 +38,7 @@ fn foo() {
3238
/// bar //~ ERROR unused doc comment
3339
mac!();
3440

41+
#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
3542
let x = /** comment */ 47; //~ ERROR unused doc comment
3643

3744
/// dox //~ ERROR unused doc comment

0 commit comments

Comments
 (0)