diff --git a/Cargo.lock b/Cargo.lock index 3c278a6a491a9..d3950502db7a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4265,6 +4265,7 @@ name = "rustc_passes" version = "0.0.0" dependencies = [ "rustc_ast", + "rustc_ast_pretty", "rustc_attr", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index c87799f1c2acc..4069fb2127e02 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -19,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_lexer = { path = "../rustc_lexer" } +rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ae8883754d6f2..9c606f3e4d459 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -524,7 +524,7 @@ impl CheckAttrVisitor<'tcx> { .struct_span_err( meta.span(), &format!( - "`#![doc({} = \"...\")]` isn't allowed as a crate level attribute", + "`#![doc({} = \"...\")]` isn't allowed as a crate-level attribute", attr_name, ), ) @@ -535,79 +535,97 @@ impl CheckAttrVisitor<'tcx> { } fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool { - if let Some(mi) = attr.meta() { - if let Some(list) = mi.meta_item_list() { - for meta in list { - if meta.has_name(sym::alias) { - if !self.check_attr_crate_level(meta, hir_id, "alias") - || !self.check_doc_alias(meta, hir_id, target) + let mut is_valid = true; + + if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) { + for meta in list { + if let Some(i_meta) = meta.meta_item() { + match i_meta.name_or_empty() { + sym::alias + if !self.check_attr_crate_level(&meta, hir_id, "alias") + || !self.check_doc_alias(&meta, hir_id, target) => { - return false; + is_valid = false } - } else if meta.has_name(sym::keyword) { - if !self.check_attr_crate_level(meta, hir_id, "keyword") - || !self.check_doc_keyword(meta, hir_id) + + sym::keyword + if !self.check_attr_crate_level(&meta, hir_id, "keyword") + || !self.check_doc_keyword(&meta, hir_id) => { - return false; + is_valid = false } - } else if meta.has_name(sym::test) { - if CRATE_HIR_ID != hir_id { + + sym::test if CRATE_HIR_ID != hir_id => { self.tcx.struct_span_lint_hir( INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| { lint.build( - "`#![doc(test(...)]` is only allowed as a crate level attribute" + "`#![doc(test(...)]` is only allowed \ + as a crate-level attribute", ) .emit(); }, ); - return false; + is_valid = false; } - } else if let Some(i_meta) = meta.meta_item() { - if ![ - sym::cfg, - sym::hidden, - sym::html_favicon_url, - sym::html_logo_url, - sym::html_no_source, - sym::html_playground_url, - sym::html_root_url, - sym::include, - sym::inline, - sym::issue_tracker_base_url, - sym::masked, - sym::no_default_passes, // deprecated - sym::no_inline, - sym::passes, // deprecated - sym::plugins, // removed, but rustdoc warns about it itself - sym::primitive, - sym::spotlight, - sym::test, - ] - .iter() - .any(|m| i_meta.has_name(*m)) - { + + // no_default_passes: deprecated + // passes: deprecated + // plugins: removed, but rustdoc warns about it itself + sym::alias + | sym::cfg + | sym::hidden + | sym::html_favicon_url + | sym::html_logo_url + | sym::html_no_source + | 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::passes + | sym::plugins + | sym::primitive + | sym::spotlight + | sym::test => {} + + _ => { self.tcx.struct_span_lint_hir( INVALID_DOC_ATTRIBUTES, hir_id, i_meta.span, |lint| { - lint.build(&format!( + let msg = format!( "unknown `doc` attribute `{}`", - i_meta.name_or_empty() - )) - .emit(); + rustc_ast_pretty::pprust::path_to_string(&i_meta.path), + ); + lint.build(&msg).emit(); }, ); - return false; + is_valid = false; } } + } else { + self.tcx.struct_span_lint_hir( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + |lint| { + lint.build(&format!("invalid `doc` attribute")).emit(); + }, + ); + is_valid = false; } } } - true + + is_valid } /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid. diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr index 9e746cba05f63..fc8095e03ca93 100644 --- a/src/test/rustdoc-ui/doc-alias-crate-level.stderr +++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr @@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]` LL | #[doc(alias = "shouldn't work!")] | ^^^^^^^^^^^^^^^^^ -error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute +error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc-alias-crate-level.rs:1:8 | LL | #![doc(alias = "crate-level-not-working")] diff --git a/src/test/rustdoc-ui/doc-attr.rs b/src/test/rustdoc-ui/doc-attr.rs index 3a5841129734d..980d1c0e2077d 100644 --- a/src/test/rustdoc-ui/doc-attr.rs +++ b/src/test/rustdoc-ui/doc-attr.rs @@ -8,3 +8,18 @@ //~^ ERROR unknown `doc` attribute //~^^ WARN pub fn foo() {} + +#[doc(123)] +//~^ ERROR invalid `doc` attribute +//~| WARN +#[doc("hello", "bar")] +//~^ ERROR invalid `doc` attribute +//~| WARN +//~| ERROR invalid `doc` attribute +//~| WARN +#[doc(foo::bar, crate::bar::baz = "bye")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN +fn bar() {} diff --git a/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr index 21479d25fc274..cc2494c92e649 100644 --- a/src/test/rustdoc-ui/doc-attr.stderr +++ b/src/test/rustdoc-ui/doc-attr.stderr @@ -13,6 +13,51 @@ LL | #![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: invalid `doc` attribute + --> $DIR/doc-attr.rs:12:7 + | +LL | #[doc(123)] + | ^^^ + | + = 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: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:7 + | +LL | #[doc("hello", "bar")] + | ^^^^^^^ + | + = 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: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:16 + | +LL | #[doc("hello", "bar")] + | ^^^^^ + | + = 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: unknown `doc` attribute `foo::bar` + --> $DIR/doc-attr.rs:20:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + | + = 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: unknown `doc` attribute `crate::bar::baz` + --> $DIR/doc-attr.rs:20:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -22,5 +67,5 @@ LL | #![doc(as_ptr)] = 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 +error: aborting due to 7 previous errors diff --git a/src/test/rustdoc-ui/doc-attr2.stderr b/src/test/rustdoc-ui/doc-attr2.stderr index eeb2c2be08551..643107318b979 100644 --- a/src/test/rustdoc-ui/doc-attr2.stderr +++ b/src/test/rustdoc-ui/doc-attr2.stderr @@ -1,4 +1,4 @@ -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:4:7 | LL | #[doc(test(no_crate_inject))] @@ -13,7 +13,7 @@ LL | #![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 +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:9:12 | LL | #![doc(test(no_crate_inject))] diff --git a/src/test/ui/attributes/doc-attr.rs b/src/test/ui/attributes/doc-attr.rs index 3a5841129734d..980d1c0e2077d 100644 --- a/src/test/ui/attributes/doc-attr.rs +++ b/src/test/ui/attributes/doc-attr.rs @@ -8,3 +8,18 @@ //~^ ERROR unknown `doc` attribute //~^^ WARN pub fn foo() {} + +#[doc(123)] +//~^ ERROR invalid `doc` attribute +//~| WARN +#[doc("hello", "bar")] +//~^ ERROR invalid `doc` attribute +//~| WARN +//~| ERROR invalid `doc` attribute +//~| WARN +#[doc(foo::bar, crate::bar::baz = "bye")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN +fn bar() {} diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr index 21479d25fc274..cc2494c92e649 100644 --- a/src/test/ui/attributes/doc-attr.stderr +++ b/src/test/ui/attributes/doc-attr.stderr @@ -13,6 +13,51 @@ LL | #![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: invalid `doc` attribute + --> $DIR/doc-attr.rs:12:7 + | +LL | #[doc(123)] + | ^^^ + | + = 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: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:7 + | +LL | #[doc("hello", "bar")] + | ^^^^^^^ + | + = 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: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:16 + | +LL | #[doc("hello", "bar")] + | ^^^^^ + | + = 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: unknown `doc` attribute `foo::bar` + --> $DIR/doc-attr.rs:20:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + | + = 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: unknown `doc` attribute `crate::bar::baz` + --> $DIR/doc-attr.rs:20:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:3:8 | @@ -22,5 +67,5 @@ LL | #![doc(as_ptr)] = 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 +error: aborting due to 7 previous errors diff --git a/src/test/ui/attributes/doc-attr2.stderr b/src/test/ui/attributes/doc-attr2.stderr index eeb2c2be08551..643107318b979 100644 --- a/src/test/ui/attributes/doc-attr2.stderr +++ b/src/test/ui/attributes/doc-attr2.stderr @@ -1,4 +1,4 @@ -error: `#![doc(test(...)]` is only allowed as a crate level attribute +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:4:7 | LL | #[doc(test(no_crate_inject))] @@ -13,7 +13,7 @@ LL | #![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 +error: `#![doc(test(...)]` is only allowed as a crate-level attribute --> $DIR/doc-attr2.rs:9:12 | LL | #![doc(test(no_crate_inject))] diff --git a/src/test/ui/rustdoc/doc-alias-crate-level.stderr b/src/test/ui/rustdoc/doc-alias-crate-level.stderr index c0467514ae1c7..bd32609ade296 100644 --- a/src/test/ui/rustdoc/doc-alias-crate-level.stderr +++ b/src/test/ui/rustdoc/doc-alias-crate-level.stderr @@ -4,7 +4,7 @@ error: '\'' character isn't allowed in `#[doc(alias = "...")]` LL | #[doc(alias = "shouldn't work!")] | ^^^^^^^^^^^^^^^^^ -error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute +error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc-alias-crate-level.rs:5:8 | LL | #![doc(alias = "not working!")] diff --git a/src/test/ui/rustdoc/doc_keyword.stderr b/src/test/ui/rustdoc/doc_keyword.stderr index d72a876163eb3..0679bb8c5a7a6 100644 --- a/src/test/ui/rustdoc/doc_keyword.stderr +++ b/src/test/ui/rustdoc/doc_keyword.stderr @@ -10,7 +10,7 @@ error: `#[doc(keyword = "...")]` can only be used on modules LL | #[doc(keyword = "hall")] | ^^^^^^^^^^^^^^^^ -error: `#![doc(keyword = "...")]` isn't allowed as a crate level attribute +error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc_keyword.rs:4:8 | LL | #![doc(keyword = "hello")]