From f2077c728c8c0a3d79fdede72e506fe9c77f72bc Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 8 May 2021 16:57:10 +0200 Subject: [PATCH] Error on conflicting `#[doc(inline)]`/`#[doc(no_inline)]` attributes --- compiler/rustc_passes/src/check_attr.rs | 100 +++++++++++++----- src/test/rustdoc-ui/invalid-doc-attr.rs | 6 ++ src/test/rustdoc-ui/invalid-doc-attr.stderr | 12 ++- src/test/ui/attributes/doc-attr2.rs | 11 -- src/test/ui/attributes/doc-attr2.stderr | 26 ----- src/test/ui/attributes/invalid-doc-attr.rs | 32 ++++++ .../ui/attributes/invalid-doc-attr.stderr | 78 ++++++++++++++ 7 files changed, 201 insertions(+), 64 deletions(-) delete mode 100644 src/test/ui/attributes/doc-attr2.rs delete mode 100644 src/test/ui/attributes/doc-attr2.stderr create mode 100644 src/test/ui/attributes/invalid-doc-attr.rs create mode 100644 src/test/ui/attributes/invalid-doc-attr.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f68b79b60434f..2e1788cfe3824 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -22,7 +22,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{MultiSpan, Span, DUMMY_SP}; pub(crate) fn target_from_impl_item<'tcx>( tcx: TyCtxt<'tcx>, @@ -67,6 +67,7 @@ impl CheckAttrVisitor<'tcx> { item: Option>, ) { let mut is_valid = true; + let mut specified_inline = None; let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { is_valid &= match attr.name_or_empty() { @@ -77,7 +78,7 @@ impl CheckAttrVisitor<'tcx> { sym::track_caller => { self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - sym::doc => self.check_doc_attrs(attr, hir_id, target), + sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline), sym::no_link => self.check_no_link(hir_id, &attr, span, target), sym::export_name => self.check_export_name(hir_id, &attr, span, target), sym::rustc_args_required_const => { @@ -564,6 +565,60 @@ impl CheckAttrVisitor<'tcx> { true } + fn check_doc_inline( + &self, + attr: &Attribute, + meta: &NestedMetaItem, + hir_id: HirId, + target: Target, + specified_inline: &mut Option<(bool, Span)>, + ) -> bool { + if target == Target::Use { + let do_inline = meta.name_or_empty() == sym::inline; + if let Some((prev_inline, prev_span)) = *specified_inline { + if do_inline != prev_inline { + let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]); + spans.push_span_label(prev_span, String::from("this attribute...")); + spans.push_span_label( + meta.span(), + String::from("...conflicts with this attribute"), + ); + self.tcx + .sess + .struct_span_err(spans, "conflicting doc inlining attributes") + .help("remove one of the conflicting attributes") + .emit(); + return false; + } + true + } else { + *specified_inline = Some((do_inline, meta.span())); + true + } + } else { + self.tcx.struct_span_lint_hir( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + |lint| { + let mut err = lint.build( + "this attribute can only be applied to a `use` item", + ); + err.span_label(meta.span(), "only applicable on `use` items"); + if attr.style == AttrStyle::Outer { + err.span_label( + self.tcx.hir().span(hir_id), + "not a `use` item", + ); + } + err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information") + .emit(); + }, + ); + false + } + } + fn check_attr_not_crate_level( &self, meta: &NestedMetaItem, @@ -628,7 +683,13 @@ impl CheckAttrVisitor<'tcx> { true } - fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool { + fn check_doc_attrs( + &self, + attr: &Attribute, + hir_id: HirId, + target: Target, + specified_inline: &mut Option<(bool, Span)>, + ) -> bool { let mut is_valid = true; 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> { is_valid = false; } - sym::inline | sym::no_inline if target != Target::Use => { - self.tcx.struct_span_lint_hir( - INVALID_DOC_ATTRIBUTES, + sym::inline | sym::no_inline + if !self.check_doc_inline( + &attr, + &meta, hir_id, - meta.span(), - |lint| { - let mut err = lint.build( - "this attribute can only be applied to a `use` item", - ); - err.span_label(meta.span(), "only applicable on `use` items"); - if attr.style == AttrStyle::Outer { - err.span_label( - self.tcx.hir().span(hir_id), - "not a `use` item", - ); - } - err.note("read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information") - .emit(); - }, - ); + target, + specified_inline, + ) => + { is_valid = false; } - sym::inline | sym::no_inline => { - // FIXME(#80275): conflicting inline attributes - } - // no_default_passes: deprecated // passes: deprecated // plugins: removed, but rustdoc warns about it itself @@ -700,10 +746,12 @@ impl CheckAttrVisitor<'tcx> { | sym::html_playground_url | sym::html_root_url | sym::include + | sym::inline | sym::issue_tracker_base_url | sym::keyword | sym::masked | sym::no_default_passes + | sym::no_inline | sym::notable_trait | sym::passes | sym::plugins diff --git a/src/test/rustdoc-ui/invalid-doc-attr.rs b/src/test/rustdoc-ui/invalid-doc-attr.rs index b8c6f7bf2ed76..de004b41e27bc 100644 --- a/src/test/rustdoc-ui/invalid-doc-attr.rs +++ b/src/test/rustdoc-ui/invalid-doc-attr.rs @@ -24,3 +24,9 @@ pub mod bar { //~| WARN is being phased out pub fn baz() {} } + +#[doc(inline)] +#[doc(no_inline)] +//~^^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +pub use bar::baz; diff --git a/src/test/rustdoc-ui/invalid-doc-attr.stderr b/src/test/rustdoc-ui/invalid-doc-attr.stderr index 3d2230aa4d2df..595ece2ea7247 100644 --- a/src/test/rustdoc-ui/invalid-doc-attr.stderr +++ b/src/test/rustdoc-ui/invalid-doc-attr.stderr @@ -41,6 +41,16 @@ LL | #![doc(test(no_crate_inject))] = note: for more information, see issue #82730 = 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:28:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + error: this attribute can only be applied at the crate level --> $DIR/invalid-doc-attr.rs:19:11 | @@ -64,5 +74,5 @@ LL | pub fn baz() {} = note: for more information, see issue #82730 = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/attributes/doc-attr2.rs b/src/test/ui/attributes/doc-attr2.rs deleted file mode 100644 index 3fb484644d7fa..0000000000000 --- a/src/test/ui/attributes/doc-attr2.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![crate_type = "lib"] -#![deny(warnings)] - -#[doc(test(no_crate_inject))] //~ ERROR -//~^ WARN -pub fn foo() {} - -pub mod bar { - #![doc(test(no_crate_inject))] //~ ERROR - //~^ WARN -} diff --git a/src/test/ui/attributes/doc-attr2.stderr b/src/test/ui/attributes/doc-attr2.stderr deleted file mode 100644 index 643107318b979..0000000000000 --- a/src/test/ui/attributes/doc-attr2.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: `#![doc(test(...)]` is only allowed as a crate-level attribute - --> $DIR/doc-attr2.rs:4:7 - | -LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/doc-attr2.rs:2:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ - = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #82730 - -error: `#![doc(test(...)]` is only allowed as a crate-level attribute - --> $DIR/doc-attr2.rs:9: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! - = note: for more information, see issue #82730 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/attributes/invalid-doc-attr.rs b/src/test/ui/attributes/invalid-doc-attr.rs new file mode 100644 index 0000000000000..de004b41e27bc --- /dev/null +++ b/src/test/ui/attributes/invalid-doc-attr.rs @@ -0,0 +1,32 @@ +#![crate_type = "lib"] +#![deny(warnings)] + +#[doc(test(no_crate_inject))] +//~^ ERROR can only be applied at the crate level +//~| WARN is being phased out +//~| HELP to apply to the crate, use an inner attribute +//~| SUGGESTION #![doc(test(no_crate_inject))] +#[doc(inline)] +//~^ ERROR can only be applied to a `use` item +//~| WARN is being phased out +pub fn foo() {} + +pub mod bar { + #![doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + //~| WARN is being phased out + + #[doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + //~| WARN is being phased out + #[doc(inline)] + //~^ ERROR can only be applied to a `use` item + //~| WARN is being phased out + pub fn baz() {} +} + +#[doc(inline)] +#[doc(no_inline)] +//~^^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +pub use bar::baz; diff --git a/src/test/ui/attributes/invalid-doc-attr.stderr b/src/test/ui/attributes/invalid-doc-attr.stderr new file mode 100644 index 0000000000000..595ece2ea7247 --- /dev/null +++ b/src/test/ui/attributes/invalid-doc-attr.stderr @@ -0,0 +1,78 @@ +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:4:7 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/invalid-doc-attr.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information +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:9:7 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +... +LL | pub fn foo() {} + | ------------ not a `use` item + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:15: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! + = note: for more information, see issue #82730 + = 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:28:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:19:11 + | +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! + = note: for more information, see issue #82730 + = 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:22:11 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +... +LL | pub fn baz() {} + | ------------ not a `use` item + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#docno_inlinedocinline for more information + +error: aborting due to 6 previous errors +