Skip to content

Commit f2077c7

Browse files
Error on conflicting #[doc(inline)]/#[doc(no_inline)] attributes
1 parent 245f582 commit f2077c7

File tree

7 files changed

+201
-64
lines changed

7 files changed

+201
-64
lines changed

compiler/rustc_passes/src/check_attr.rs

+74-26
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_session::lint::builtin::{
2222
};
2323
use rustc_session::parse::feature_err;
2424
use rustc_span::symbol::{sym, Symbol};
25-
use rustc_span::{Span, DUMMY_SP};
25+
use rustc_span::{MultiSpan, Span, DUMMY_SP};
2626

2727
pub(crate) fn target_from_impl_item<'tcx>(
2828
tcx: TyCtxt<'tcx>,
@@ -67,6 +67,7 @@ impl CheckAttrVisitor<'tcx> {
6767
item: Option<ItemLike<'_>>,
6868
) {
6969
let mut is_valid = true;
70+
let mut specified_inline = None;
7071
let attrs = self.tcx.hir().attrs(hir_id);
7172
for attr in attrs {
7273
is_valid &= match attr.name_or_empty() {
@@ -77,7 +78,7 @@ impl CheckAttrVisitor<'tcx> {
7778
sym::track_caller => {
7879
self.check_track_caller(hir_id, &attr.span, attrs, span, target)
7980
}
80-
sym::doc => self.check_doc_attrs(attr, hir_id, target),
81+
sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline),
8182
sym::no_link => self.check_no_link(hir_id, &attr, span, target),
8283
sym::export_name => self.check_export_name(hir_id, &attr, span, target),
8384
sym::rustc_args_required_const => {
@@ -564,6 +565,60 @@ impl CheckAttrVisitor<'tcx> {
564565
true
565566
}
566567

568+
fn check_doc_inline(
569+
&self,
570+
attr: &Attribute,
571+
meta: &NestedMetaItem,
572+
hir_id: HirId,
573+
target: Target,
574+
specified_inline: &mut Option<(bool, Span)>,
575+
) -> bool {
576+
if target == Target::Use {
577+
let do_inline = meta.name_or_empty() == sym::inline;
578+
if let Some((prev_inline, prev_span)) = *specified_inline {
579+
if do_inline != prev_inline {
580+
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
581+
spans.push_span_label(prev_span, String::from("this attribute..."));
582+
spans.push_span_label(
583+
meta.span(),
584+
String::from("...conflicts with this attribute"),
585+
);
586+
self.tcx
587+
.sess
588+
.struct_span_err(spans, "conflicting doc inlining attributes")
589+
.help("remove one of the conflicting attributes")
590+
.emit();
591+
return false;
592+
}
593+
true
594+
} else {
595+
*specified_inline = Some((do_inline, meta.span()));
596+
true
597+
}
598+
} else {
599+
self.tcx.struct_span_lint_hir(
600+
INVALID_DOC_ATTRIBUTES,
601+
hir_id,
602+
meta.span(),
603+
|lint| {
604+
let mut err = lint.build(
605+
"this attribute can only be applied to a `use` item",
606+
);
607+
err.span_label(meta.span(), "only applicable on `use` items");
608+
if attr.style == AttrStyle::Outer {
609+
err.span_label(
610+
self.tcx.hir().span(hir_id),
611+
"not a `use` item",
612+
);
613+
}
614+
err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information")
615+
.emit();
616+
},
617+
);
618+
false
619+
}
620+
}
621+
567622
fn check_attr_not_crate_level(
568623
&self,
569624
meta: &NestedMetaItem,
@@ -628,7 +683,13 @@ impl CheckAttrVisitor<'tcx> {
628683
true
629684
}
630685

631-
fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
686+
fn check_doc_attrs(
687+
&self,
688+
attr: &Attribute,
689+
hir_id: HirId,
690+
target: Target,
691+
specified_inline: &mut Option<(bool, Span)>,
692+
) -> bool {
632693
let mut is_valid = true;
633694

634695
if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) {
@@ -661,33 +722,18 @@ impl CheckAttrVisitor<'tcx> {
661722
is_valid = false;
662723
}
663724

664-
sym::inline | sym::no_inline if target != Target::Use => {
665-
self.tcx.struct_span_lint_hir(
666-
INVALID_DOC_ATTRIBUTES,
725+
sym::inline | sym::no_inline
726+
if !self.check_doc_inline(
727+
&attr,
728+
&meta,
667729
hir_id,
668-
meta.span(),
669-
|lint| {
670-
let mut err = lint.build(
671-
"this attribute can only be applied to a `use` item",
672-
);
673-
err.span_label(meta.span(), "only applicable on `use` items");
674-
if attr.style == AttrStyle::Outer {
675-
err.span_label(
676-
self.tcx.hir().span(hir_id),
677-
"not a `use` item",
678-
);
679-
}
680-
err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information")
681-
.emit();
682-
},
683-
);
730+
target,
731+
specified_inline,
732+
) =>
733+
{
684734
is_valid = false;
685735
}
686736

687-
sym::inline | sym::no_inline => {
688-
// FIXME(#80275): conflicting inline attributes
689-
}
690-
691737
// no_default_passes: deprecated
692738
// passes: deprecated
693739
// plugins: removed, but rustdoc warns about it itself
@@ -700,10 +746,12 @@ impl CheckAttrVisitor<'tcx> {
700746
| sym::html_playground_url
701747
| sym::html_root_url
702748
| sym::include
749+
| sym::inline
703750
| sym::issue_tracker_base_url
704751
| sym::keyword
705752
| sym::masked
706753
| sym::no_default_passes
754+
| sym::no_inline
707755
| sym::notable_trait
708756
| sym::passes
709757
| sym::plugins

src/test/rustdoc-ui/invalid-doc-attr.rs

+6
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ pub mod bar {
2424
//~| WARN is being phased out
2525
pub fn baz() {}
2626
}
27+
28+
#[doc(inline)]
29+
#[doc(no_inline)]
30+
//~^^ ERROR conflicting doc inlining attributes
31+
//~| HELP remove one of the conflicting attributes
32+
pub use bar::baz;

src/test/rustdoc-ui/invalid-doc-attr.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ LL | #![doc(test(no_crate_inject))]
4141
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
4242
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
4343

44+
error: conflicting doc inlining attributes
45+
--> $DIR/invalid-doc-attr.rs:28:7
46+
|
47+
LL | #[doc(inline)]
48+
| ^^^^^^ this attribute...
49+
LL | #[doc(no_inline)]
50+
| ^^^^^^^^^ ...conflicts with this attribute
51+
|
52+
= help: remove one of the conflicting attributes
53+
4454
error: this attribute can only be applied at the crate level
4555
--> $DIR/invalid-doc-attr.rs:19:11
4656
|
@@ -64,5 +74,5 @@ LL | pub fn baz() {}
6474
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
6575
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
6676

67-
error: aborting due to 5 previous errors
77+
error: aborting due to 6 previous errors
6878

src/test/ui/attributes/doc-attr2.rs

-11
This file was deleted.

src/test/ui/attributes/doc-attr2.stderr

-26
This file was deleted.
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![crate_type = "lib"]
2+
#![deny(warnings)]
3+
4+
#[doc(test(no_crate_inject))]
5+
//~^ ERROR can only be applied at the crate level
6+
//~| WARN is being phased out
7+
//~| HELP to apply to the crate, use an inner attribute
8+
//~| SUGGESTION #![doc(test(no_crate_inject))]
9+
#[doc(inline)]
10+
//~^ ERROR can only be applied to a `use` item
11+
//~| WARN is being phased out
12+
pub fn foo() {}
13+
14+
pub mod bar {
15+
#![doc(test(no_crate_inject))]
16+
//~^ ERROR can only be applied at the crate level
17+
//~| WARN is being phased out
18+
19+
#[doc(test(no_crate_inject))]
20+
//~^ ERROR can only be applied at the crate level
21+
//~| WARN is being phased out
22+
#[doc(inline)]
23+
//~^ ERROR can only be applied to a `use` item
24+
//~| WARN is being phased out
25+
pub fn baz() {}
26+
}
27+
28+
#[doc(inline)]
29+
#[doc(no_inline)]
30+
//~^^ ERROR conflicting doc inlining attributes
31+
//~| HELP remove one of the conflicting attributes
32+
pub use bar::baz;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
error: this attribute can only be applied at the crate level
2+
--> $DIR/invalid-doc-attr.rs:4:7
3+
|
4+
LL | #[doc(test(no_crate_inject))]
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/invalid-doc-attr.rs:2:9
9+
|
10+
LL | #![deny(warnings)]
11+
| ^^^^^^^^
12+
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
13+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
14+
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
15+
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
16+
help: to apply to the crate, use an inner attribute
17+
|
18+
LL | #![doc(test(no_crate_inject))]
19+
|
20+
21+
error: this attribute can only be applied to a `use` item
22+
--> $DIR/invalid-doc-attr.rs:9:7
23+
|
24+
LL | #[doc(inline)]
25+
| ^^^^^^ only applicable on `use` items
26+
...
27+
LL | pub fn foo() {}
28+
| ------------ not a `use` item
29+
|
30+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
31+
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
32+
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
33+
34+
error: this attribute can only be applied at the crate level
35+
--> $DIR/invalid-doc-attr.rs:15:12
36+
|
37+
LL | #![doc(test(no_crate_inject))]
38+
| ^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
41+
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
42+
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
43+
44+
error: conflicting doc inlining attributes
45+
--> $DIR/invalid-doc-attr.rs:28:7
46+
|
47+
LL | #[doc(inline)]
48+
| ^^^^^^ this attribute...
49+
LL | #[doc(no_inline)]
50+
| ^^^^^^^^^ ...conflicts with this attribute
51+
|
52+
= help: remove one of the conflicting attributes
53+
54+
error: this attribute can only be applied at the crate level
55+
--> $DIR/invalid-doc-attr.rs:19:11
56+
|
57+
LL | #[doc(test(no_crate_inject))]
58+
| ^^^^^^^^^^^^^^^^^^^^^
59+
|
60+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
61+
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
62+
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information
63+
64+
error: this attribute can only be applied to a `use` item
65+
--> $DIR/invalid-doc-attr.rs:22:11
66+
|
67+
LL | #[doc(inline)]
68+
| ^^^^^^ only applicable on `use` items
69+
...
70+
LL | pub fn baz() {}
71+
| ------------ not a `use` item
72+
|
73+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
74+
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
75+
= note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information
76+
77+
error: aborting due to 6 previous errors
78+

0 commit comments

Comments
 (0)