diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 26fb53baf2e4..1fd7b702e92f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -2,7 +2,6 @@ #![allow(unused_imports)] use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; -use rustc_errors::MultiSpan; use rustc_feature::template; use rustc_hir::attrs::{ AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, @@ -18,7 +17,7 @@ use crate::fluent_generated as fluent; use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, PathParser}; use crate::session_diagnostics::{ DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttributeNotAttribute, - DocKeywordConflict, DocKeywordNotKeyword, + DocKeywordNotKeyword, }; fn check_keyword(cx: &mut AcceptContext<'_, '_, S>, keyword: Symbol, span: Span) -> bool { @@ -204,19 +203,7 @@ impl DocParser { return; } - let span = path.span(); - - if let Some((prev_inline, prev_span)) = self.attribute.inline { - if prev_inline == inline { - let mut spans = MultiSpan::from_spans(vec![prev_span, span]); - spans.push_span_label(prev_span, fluent::attr_parsing_doc_inline_conflict_first); - spans.push_span_label(span, fluent::attr_parsing_doc_inline_conflict_second); - cx.emit_err(DocKeywordConflict { spans }); - return; - } - } - - self.attribute.inline = Some((inline, span)); + self.attribute.inline.push((inline, path.span())); } fn parse_cfg<'c, S: Stage>( diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 26b615448e3b..38ae597000d2 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -4,7 +4,6 @@ use rustc_ast::{self as ast}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, }; use rustc_feature::AttributeTemplate; use rustc_hir::AttrPath; @@ -589,14 +588,6 @@ pub(crate) struct DocAliasDuplicated { pub first_defn: Span, } -#[derive(Diagnostic)] -#[diag(attr_parsing_doc_inline_conflict)] -#[help] -pub(crate) struct DocKeywordConflict { - #[primary_span] - pub spans: MultiSpan, -} - #[derive(Diagnostic)] #[diag(attr_parsing_link_ordinal_out_of_range)] #[note] diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 4e1de8e5aeae..0419e219afe4 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -476,7 +476,9 @@ pub struct CfgHideShow { pub struct DocAttribute { pub aliases: FxIndexMap, pub hidden: Option, - pub inline: Option<(DocInline, Span)>, + // Because we need to emit the error if there is more than one `inline` attribute on an item + // at the same time as the other doc attributes, we store a list instead of using `Option`. + pub inline: ThinVec<(DocInline, Span)>, // unstable pub cfg: ThinVec, @@ -511,7 +513,7 @@ impl Default for DocAttribute { Self { aliases: FxIndexMap::default(), hidden: None, - inline: None, + inline: ThinVec::new(), cfg: ThinVec::new(), auto_cfg: ThinVec::new(), auto_cfg_change: ThinVec::new(), diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9a1cf7f349fd..2069c06c3f77 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -880,7 +880,7 @@ fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState<'_>) -> bool } else if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { // If this is a `doc` attribute that doesn't have anything except maybe `inline` (as in // `#[doc(inline)]`), then we can remove it. It won't be inlinable in downstream crates. - if d.inline.is_none() { + if d.inline.is_empty() { should_encode = true; if d.hidden.is_some() { state.is_doc_hidden = true; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 007ce22c01e6..4e8973e4928b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -107,10 +107,10 @@ passes_diagnostic_item_first_defined = the diagnostic item is first defined here passes_doc_alias_bad_location = - doc alias attribute isn't allowed on {$location} + `#[doc(alias = "...")]` isn't allowed on {$location} passes_doc_alias_not_an_alias = - {$attr_str} is the same as the item's name + `#[doc(alias = "{$attr_str}"]` is the same as the item's name passes_doc_attr_not_crate_level = `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute @@ -118,7 +118,15 @@ passes_doc_attr_not_crate_level = passes_doc_fake_variadic_not_valid = `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity +passes_doc_inline_conflict = + conflicting doc inlining attributes + .help = remove one of the conflicting attributes +passes_doc_inline_conflict_first = + this attribute... + +passes_doc_inline_conflict_second = + {"."}..conflicts with this attribute passes_doc_inline_only_use = this attribute can only be applied to a `use` item diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bae15de4bf88..3f29d943e7d3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -13,13 +13,14 @@ use rustc_abi::{Align, ExternAbi, Size}; use rustc_ast::{AttrStyle, LitKind, MetaItemKind, ast}; use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{DiagCtxtHandle, IntoDiagArg, StashKey}; +use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, }; use rustc_hir::attrs::{ - AttributeKind, DocAttribute, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet, + AttributeKind, DocAttribute, DocInline, InlineAttr, MirDialect, MirPhase, ReprAttr, + SanitizerSet, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; @@ -881,7 +882,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// already seen an inlining attribute for this item. /// If so, `specified_inline` holds the value and the span of /// the first `inline`/`no_inline` attribute. - fn check_doc_inline(&self, span: Span, hir_id: HirId, target: Target) { + fn check_doc_inline(&self, hir_id: HirId, target: Target, inline: &[(DocInline, Span)]) { + let span = match inline { + [] => return, + [(_, span)] => *span, + [(inline, span), rest @ ..] => { + for (inline2, span2) in rest { + if inline2 != inline { + let mut spans = MultiSpan::from_spans(vec![*span, *span2]); + spans.push_span_label(*span, fluent::passes_doc_inline_conflict_first); + spans.push_span_label(*span2, fluent::passes_doc_inline_conflict_second); + self.dcx().emit_err(errors::DocInlineConflict { spans }); + return; + } + } + *span + } + }; + match target { Target::Use | Target::ExternCrate => {} _ => { @@ -1050,9 +1068,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - if let Some((_, span)) = inline { - self.check_doc_inline(*span, hir_id, target) - } + self.check_doc_inline(hir_id, target, inline); if let Some(span) = rust_logo { if self.check_attr_crate_level(*span, hir_id) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index b693aaf76923..3a2908d14184 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -176,6 +176,14 @@ pub(crate) struct DocSearchUnboxInvalid { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_doc_inline_conflict)] +#[help] +pub(crate) struct DocInlineConflict { + #[primary_span] + pub spans: MultiSpan, +} + #[derive(LintDiagnostic)] #[diag(passes_doc_inline_only_use)] #[note] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bea4398ccf86..dd5c50d2ba37 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -199,7 +199,7 @@ fn generate_item_with_correct_attrs( let import_is_inline = find_attr!( inline::load_attrs(cx, import_id.to_def_id()), AttributeKind::Doc(d) - if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline) + if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) ) || (is_glob_import(cx.tcx, import_id) && (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id))); attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); @@ -2921,7 +2921,7 @@ fn clean_extern_crate<'tcx>( matches!( a, hir::Attribute::Parsed(AttributeKind::Doc(d)) - if d.inline.is_some_and(|(i, _)| i == DocInline::Inline)) + if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline)) }) && !cx.is_json_output(); @@ -2986,9 +2986,9 @@ fn clean_use_statement_inner<'tcx>( let attrs = cx.tcx.hir_attrs(import.hir_id()); let inline_attr = find_attr!( attrs, - AttributeKind::Doc(d) if d.inline.is_some_and(|(i, _)| i == DocInline::Inline) => d + AttributeKind::Doc(d) if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline) => d ) - .and_then(|d| d.inline); + .and_then(|d| d.inline.first()); let pub_underscore = visibility.is_public() && name == Some(kw::Underscore); let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); let import_def_id = import.owner_id.def_id; @@ -3009,7 +3009,7 @@ fn clean_use_statement_inner<'tcx>( if pub_underscore && let Some((_, inline_span)) = inline_attr { struct_span_code_err!( cx.tcx.dcx(), - inline_span, + *inline_span, E0780, "anonymous imports cannot be inlined" ) @@ -3026,7 +3026,9 @@ fn clean_use_statement_inner<'tcx>( || pub_underscore || attrs.iter().any(|a| matches!( a, - hir::Attribute::Parsed(AttributeKind::Doc(d)) if d.hidden.is_some() || d.inline.is_some_and(|(i, _)| i == DocInline::NoInline))); + hir::Attribute::Parsed(AttributeKind::Doc(d)) + if d.hidden.is_some() || d.inline.first().is_some_and(|(i, _)| *i == DocInline::NoInline) + )); // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a0e359032f9b..13be1a04dbc5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,6 +32,7 @@ extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_ast_pretty; +extern crate rustc_attr_parsing; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; @@ -75,6 +76,7 @@ use std::process; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::lints::DelayedLint; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; @@ -900,6 +902,18 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { return; } + for owner_id in tcx.hir_crate_items(()).delayed_lint_items() { + if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { + for lint in &delayed_lints.lints { + match lint { + DelayedLint::AttributeParsing(attribute_lint) => { + rustc_attr_parsing::emit_attribute_lint(attribute_lint, tcx) + } + } + } + } + } + if render_opts.dep_info().is_some() { rustc_interface::passes::write_dep_info(tcx); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index d6da8615d57e..0f4460bed35a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -247,8 +247,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let document_hidden = self.cx.document_hidden(); let use_attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. - let is_no_inline = find_attr!(use_attrs, AttributeKind::Doc(d) if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline)) - || (document_hidden && use_attrs.iter().any(|attr| attr.is_doc_hidden())); + let is_no_inline = find_attr!( + use_attrs, + AttributeKind::Doc(d) + if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::NoInline) + ) || (document_hidden + && use_attrs.iter().any(|attr| attr.is_doc_hidden())); if is_no_inline { return false; @@ -465,7 +469,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // If there was a private module in the current path then don't bother inlining // anything as it will probably be stripped anyway. if is_pub && self.inside_public_path { - let please_inline = find_attr!(attrs, AttributeKind::Doc(d) if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline)); + let please_inline = find_attr!( + attrs, + AttributeKind::Doc(d) + if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) + ); let ident = match kind { hir::UseKind::Single(ident) => Some(ident.name), hir::UseKind::Glob => None, diff --git a/tests/rustdoc-ui/bad-render-options.rs b/tests/rustdoc-ui/bad-render-options.rs index f2cfd4b76fa8..0522f68cb6c2 100644 --- a/tests/rustdoc-ui/bad-render-options.rs +++ b/tests/rustdoc-ui/bad-render-options.rs @@ -1,11 +1,29 @@ // regression test for https://github.com/rust-lang/rust/issues/149187 -#![doc(html_favicon_url)] //~ ERROR: `doc(html_favicon_url)` expects a string value [invalid_doc_attributes] -#![doc(html_logo_url)] //~ ERROR: `doc(html_logo_url)` expects a string value [invalid_doc_attributes] -#![doc(html_playground_url)] //~ ERROR: `doc(html_playground_url)` expects a string value [invalid_doc_attributes] -#![doc(issue_tracker_base_url)] //~ ERROR expects a string value -#![doc(html_favicon_url = 1)] //~ ERROR expects a string value -#![doc(html_logo_url = 2)] //~ ERROR expects a string value -#![doc(html_playground_url = 3)] //~ ERROR expects a string value -#![doc(issue_tracker_base_url = 4)] //~ ERROR expects a string value -#![doc(html_no_source = "asdf")] //~ ERROR `doc(html_no_source)` does not accept a value [invalid_doc_attributes] +#![doc(html_favicon_url)] +//~^ ERROR: malformed `doc` attribute +//~| NOTE expected this to be of the form `html_favicon_url = "..."` +#![doc(html_logo_url)] +//~^ ERROR: malformed `doc` attribute +//~| NOTE expected this to be of the form `html_logo_url = "..."` +#![doc(html_playground_url)] +//~^ ERROR: malformed `doc` attribute +//~| NOTE expected this to be of the form `html_playground_url = "..."` +#![doc(issue_tracker_base_url)] +//~^ ERROR: malformed `doc` attribute +//~| NOTE expected this to be of the form `issue_tracker_base_url = "..."` +#![doc(html_favicon_url = 1)] +//~^ ERROR malformed `doc` attribute +//~| NOTE expected a string literal +#![doc(html_logo_url = 2)] +//~^ ERROR malformed `doc` attribute +//~| NOTE expected a string literal +#![doc(html_playground_url = 3)] +//~^ ERROR malformed `doc` attribute +//~| NOTE expected a string literal +#![doc(issue_tracker_base_url = 4)] +//~^ ERROR malformed `doc` attribute +//~| NOTE expected a string literal +#![doc(html_no_source = "asdf")] +//~^ ERROR malformed `doc` attribute +//~| NOTE didn't expect any arguments here diff --git a/tests/rustdoc-ui/bad-render-options.stderr b/tests/rustdoc-ui/bad-render-options.stderr index 9d503363c0bd..e7f33f4dff1d 100644 --- a/tests/rustdoc-ui/bad-render-options.stderr +++ b/tests/rustdoc-ui/bad-render-options.stderr @@ -1,58 +1,211 @@ -error: `doc(html_favicon_url)` expects a string value - --> $DIR/bad-render-options.rs:3:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:3:1 | LL | #![doc(html_favicon_url)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^----------------^^ + | | + | expected this to be of the form `html_favicon_url = "..."` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_favicon_url)] +LL + #![doc = "string"] + | +LL - #![doc(html_favicon_url)] +LL + #![doc(hidden)] + | +LL - #![doc(html_favicon_url)] +LL + #![doc(inline)] + | +LL - #![doc(html_favicon_url)] +LL + #![doc(test)] | - = note: `#[deny(invalid_doc_attributes)]` on by default -error: `doc(html_logo_url)` expects a string value - --> $DIR/bad-render-options.rs:4:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:6:1 | LL | #![doc(html_logo_url)] - | ^^^^^^^^^^^^^ + | ^^^^^^^-------------^^ + | | + | expected this to be of the form `html_logo_url = "..."` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_logo_url)] +LL + #![doc = "string"] + | +LL - #![doc(html_logo_url)] +LL + #![doc(hidden)] + | +LL - #![doc(html_logo_url)] +LL + #![doc(inline)] + | +LL - #![doc(html_logo_url)] +LL + #![doc(test)] + | -error: `doc(html_playground_url)` expects a string value - --> $DIR/bad-render-options.rs:5:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:9:1 | LL | #![doc(html_playground_url)] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^-------------------^^ + | | + | expected this to be of the form `html_playground_url = "..."` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_playground_url)] +LL + #![doc = "string"] + | +LL - #![doc(html_playground_url)] +LL + #![doc(hidden)] + | +LL - #![doc(html_playground_url)] +LL + #![doc(inline)] + | +LL - #![doc(html_playground_url)] +LL + #![doc(test)] + | -error: `doc(issue_tracker_base_url)` expects a string value - --> $DIR/bad-render-options.rs:6:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:12:1 | LL | #![doc(issue_tracker_base_url)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^----------------------^^ + | | + | expected this to be of the form `issue_tracker_base_url = "..."` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(issue_tracker_base_url)] +LL + #![doc = "string"] + | +LL - #![doc(issue_tracker_base_url)] +LL + #![doc(hidden)] + | +LL - #![doc(issue_tracker_base_url)] +LL + #![doc(inline)] + | +LL - #![doc(issue_tracker_base_url)] +LL + #![doc(test)] + | -error: `doc(html_favicon_url)` expects a string value - --> $DIR/bad-render-options.rs:7:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:15:1 | LL | #![doc(html_favicon_url = 1)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_favicon_url = 1)] +LL + #![doc = "string"] + | +LL - #![doc(html_favicon_url = 1)] +LL + #![doc(hidden)] + | +LL - #![doc(html_favicon_url = 1)] +LL + #![doc(inline)] + | +LL - #![doc(html_favicon_url = 1)] +LL + #![doc(test)] + | -error: `doc(html_logo_url)` expects a string value - --> $DIR/bad-render-options.rs:8:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:18:1 | LL | #![doc(html_logo_url = 2)] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_logo_url = 2)] +LL + #![doc = "string"] + | +LL - #![doc(html_logo_url = 2)] +LL + #![doc(hidden)] + | +LL - #![doc(html_logo_url = 2)] +LL + #![doc(inline)] + | +LL - #![doc(html_logo_url = 2)] +LL + #![doc(test)] + | -error: `doc(html_playground_url)` expects a string value - --> $DIR/bad-render-options.rs:9:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:21:1 | LL | #![doc(html_playground_url = 3)] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_playground_url = 3)] +LL + #![doc = "string"] + | +LL - #![doc(html_playground_url = 3)] +LL + #![doc(hidden)] + | +LL - #![doc(html_playground_url = 3)] +LL + #![doc(inline)] + | +LL - #![doc(html_playground_url = 3)] +LL + #![doc(test)] + | -error: `doc(issue_tracker_base_url)` expects a string value - --> $DIR/bad-render-options.rs:10:8 +error[E0539]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:24:1 | LL | #![doc(issue_tracker_base_url = 4)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(issue_tracker_base_url = 4)] +LL + #![doc = "string"] + | +LL - #![doc(issue_tracker_base_url = 4)] +LL + #![doc(hidden)] + | +LL - #![doc(issue_tracker_base_url = 4)] +LL + #![doc(inline)] + | +LL - #![doc(issue_tracker_base_url = 4)] +LL + #![doc(test)] + | -error: `doc(html_no_source)` does not accept a value - --> $DIR/bad-render-options.rs:11:8 +error[E0565]: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:27:1 | LL | #![doc(html_no_source = "asdf")] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^--------^^ + | | + | didn't expect any arguments here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #![doc(html_no_source = "asdf")] +LL + #![doc = "string"] + | +LL - #![doc(html_no_source = "asdf")] +LL + #![doc(hidden)] + | +LL - #![doc(html_no_source = "asdf")] +LL + #![doc(inline)] + | +LL - #![doc(html_no_source = "asdf")] +LL + #![doc(test)] + | error: aborting due to 9 previous errors +Some errors have detailed explanations: E0539, E0565. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/rustdoc-ui/cfg-hide-show-conflict.stderr b/tests/rustdoc-ui/cfg-hide-show-conflict.stderr index 22231e82cd7b..384a9f1a0b1f 100644 --- a/tests/rustdoc-ui/cfg-hide-show-conflict.stderr +++ b/tests/rustdoc-ui/cfg-hide-show-conflict.stderr @@ -1,14 +1,14 @@ error: same `cfg` was in `auto_cfg(hide(...))` and `auto_cfg(show(...))` on the same item - --> $DIR/cfg-hide-show-conflict.rs:3:31 + --> $DIR/cfg-hide-show-conflict.rs:3:8 | LL | #![doc(auto_cfg(show(windows, target_os = "linux")))] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | note: first change was here - --> $DIR/cfg-hide-show-conflict.rs:2:22 + --> $DIR/cfg-hide-show-conflict.rs:2:8 | LL | #![doc(auto_cfg(hide(target_os = "linux")))] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr index 85c9516236c9..b8e1863ce560 100644 --- a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr +++ b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr @@ -1,26 +1,26 @@ error: `#[doc(alias = "...")]` isn't allowed on foreign module - --> $DIR/check-doc-alias-attr-location.rs:7:7 + --> $DIR/check-doc-alias-attr-location.rs:7:15 | LL | #[doc(alias = "foo")] - | ^^^^^^^^^^^^^ + | ^^^^^ error: `#[doc(alias = "...")]` isn't allowed on implementation block - --> $DIR/check-doc-alias-attr-location.rs:10:7 + --> $DIR/check-doc-alias-attr-location.rs:10:15 | LL | #[doc(alias = "bar")] - | ^^^^^^^^^^^^^ + | ^^^^^ error: `#[doc(alias = "...")]` isn't allowed on implementation block - --> $DIR/check-doc-alias-attr-location.rs:16:7 + --> $DIR/check-doc-alias-attr-location.rs:16:15 | LL | #[doc(alias = "foobar")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block - --> $DIR/check-doc-alias-attr-location.rs:18:11 + --> $DIR/check-doc-alias-attr-location.rs:18:19 | LL | #[doc(alias = "assoc")] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/rustdoc-ui/check-doc-alias-attr.stderr b/tests/rustdoc-ui/check-doc-alias-attr.stderr index 250568be3333..06d5c6535191 100644 --- a/tests/rustdoc-ui/check-doc-alias-attr.stderr +++ b/tests/rustdoc-ui/check-doc-alias-attr.stderr @@ -4,11 +4,28 @@ error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of s LL | #[doc(alias)] | ^^^^^ -error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]` - --> $DIR/check-doc-alias-attr.rs:8:7 +error[E0539]: malformed `doc` attribute input + --> $DIR/check-doc-alias-attr.rs:8:1 | LL | #[doc(alias = 0)] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^-^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[doc(alias = 0)] +LL + #[doc = "string"] + | +LL - #[doc(alias = 0)] +LL + #[doc(hidden)] + | +LL - #[doc(alias = 0)] +LL + #[doc(inline)] + | +LL - #[doc(alias = 0)] +LL + #[doc(test)] + | error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:9:15 @@ -54,25 +71,42 @@ error: `#[doc(alias = "...")]` attribute cannot have empty value LL | #[doc(alias = "")] | ^^ -error: `#[doc(alias("a"))]` expects string literals - --> $DIR/check-doc-alias-attr.rs:19:13 +error[E0539]: malformed `doc` attribute input + --> $DIR/check-doc-alias-attr.rs:19:1 | LL | #[doc(alias(0))] - | ^ + | ^^^^^^^^^^^^-^^^ + | | + | expected a string literal here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[doc(alias(0))] +LL + #[doc = "string"] + | +LL - #[doc(alias(0))] +LL + #[doc(hidden)] + | +LL - #[doc(alias(0))] +LL + #[doc(inline)] + | +LL - #[doc(alias(0))] +LL + #[doc(test)] + | -error: '"' character isn't allowed in `#[doc(alias("..."))]` +error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:20:13 | LL | #[doc(alias("\""))] | ^^^^ -error: '\n' character isn't allowed in `#[doc(alias("..."))]` +error: '\n' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:21:13 | LL | #[doc(alias("\n"))] | ^^^^ -error: '\n' character isn't allowed in `#[doc(alias("..."))]` +error: '\n' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:22:13 | LL | #[doc(alias(" @@ -80,25 +114,25 @@ LL | #[doc(alias(" LL | | "))] | |_^ -error: '\t' character isn't allowed in `#[doc(alias("..."))]` +error: '\t' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:24:13 | LL | #[doc(alias("\t"))] | ^^^^ -error: `#[doc(alias("..."))]` cannot start or end with ' ' +error: `#[doc(alias = "...")]` cannot start or end with ' ' --> $DIR/check-doc-alias-attr.rs:25:13 | LL | #[doc(alias(" hello"))] | ^^^^^^^^ -error: `#[doc(alias("..."))]` cannot start or end with ' ' +error: `#[doc(alias = "...")]` cannot start or end with ' ' --> $DIR/check-doc-alias-attr.rs:26:13 | LL | #[doc(alias("hello "))] | ^^^^^^^^ -error: `#[doc(alias("..."))]` attribute cannot have empty value +error: `#[doc(alias = "...")]` attribute cannot have empty value --> $DIR/check-doc-alias-attr.rs:27:13 | LL | #[doc(alias(""))] @@ -106,3 +140,4 @@ LL | #[doc(alias(""))] error: aborting due to 17 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.stderr b/tests/rustdoc-ui/doc-alias-assoc-const.stderr index cc628c39400b..7566ec840da7 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.stderr +++ b/tests/rustdoc-ui/doc-alias-assoc-const.stderr @@ -1,8 +1,8 @@ error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block - --> $DIR/doc-alias-assoc-const.rs:8:11 + --> $DIR/doc-alias-assoc-const.rs:8:19 | LL | #[doc(alias = "CONST_BAZ")] - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doc-alias-same-name.stderr b/tests/rustdoc-ui/doc-alias-same-name.stderr index a9da75c0171c..a76ff5ee0b67 100644 --- a/tests/rustdoc-ui/doc-alias-same-name.stderr +++ b/tests/rustdoc-ui/doc-alias-same-name.stderr @@ -1,8 +1,8 @@ -error: `#[doc(alias = "...")]` is the same as the item's name - --> $DIR/doc-alias-same-name.rs:3:7 +error: `#[doc(alias = "Foo"]` is the same as the item's name + --> $DIR/doc-alias-same-name.rs:3:15 | LL | #[doc(alias = "Foo")] - | ^^^^^^^^^^^^^ + | ^^^^^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doc-include-suggestion.stderr b/tests/rustdoc-ui/doc-include-suggestion.stderr index 1b4b78a8f263..ea5261e5bbd4 100644 --- a/tests/rustdoc-ui/doc-include-suggestion.stderr +++ b/tests/rustdoc-ui/doc-include-suggestion.stderr @@ -2,7 +2,7 @@ error: unknown `doc` attribute `include` --> $DIR/doc-include-suggestion.rs:1:7 | LL | #[doc(include = "external-cross-doc.md")] - | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]` + | ^^^^^^^ help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]` | = note: `#[deny(invalid_doc_attributes)]` on by default diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr index c63c8d607fa0..acbe6ef69dd5 100644 --- a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr +++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr @@ -1,16 +1,16 @@ error: `#![doc(auto_cfg(hide(...)))]` expects a list of items - --> $DIR/doc_cfg_hide.rs:2:8 + --> $DIR/doc_cfg_hide.rs:2:17 | LL | #![doc(auto_cfg(hide = "test"))] - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = note: `#[deny(invalid_doc_attributes)]` on by default error: `#![doc(auto_cfg(hide(...)))]` expects a list of items - --> $DIR/doc_cfg_hide.rs:3:8 + --> $DIR/doc_cfg_hide.rs:3:17 | LL | #![doc(auto_cfg(hide))] - | ^^^^^^^^^^^^^^ + | ^^^^ error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items --> $DIR/doc_cfg_hide.rs:4:22 diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs index e1cc08ca2427..a8c42b8fd79c 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs @@ -6,8 +6,6 @@ #[doc(test(no_crate_inject))] //~^ ERROR can only be applied at the crate level -//~| HELP to apply to the crate, use an inner attribute -//~| SUGGESTION ! #[doc(inline)] //~^ ERROR can only be applied to a `use` item pub fn foo() {} diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr index 7621999a8ca5..82e1b62b57a6 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr @@ -1,18 +1,14 @@ error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:7:7 + --> $DIR/invalid-doc-attr.rs:7:12 | LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: read 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:9:7 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -23,15 +19,15 @@ LL | pub fn foo() {} = note: read 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:14:17 | LL | #![doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: read for more information error: conflicting doc inlining attributes - --> $DIR/invalid-doc-attr.rs:26:7 + --> $DIR/invalid-doc-attr.rs:24:7 | LL | #[doc(inline)] | ^^^^^^ this attribute... @@ -41,7 +37,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:30:7 | LL | #[doc(masked)] | ^^^^^^ only applicable on `extern crate` items @@ -52,7 +48,7 @@ LL | pub struct Masked; = note: read 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:34:7 | LL | #[doc(masked)] | ^^^^^^ not applicable on `extern crate self` items @@ -63,21 +59,27 @@ LL | pub extern crate self as reexport; error: this attribute can only be applied to an `extern crate` item --> $DIR/invalid-doc-attr.rs:4:8 | -LL | #![doc(masked)] - | ^^^^^^ only applicable on `extern crate` items +LL | / #![crate_type = "lib"] +LL | | #![feature(doc_masked)] +LL | | +LL | | #![doc(masked)] + | | ^^^^^^ only applicable on `extern crate` items +... | +LL | | pub extern crate self as reexport; + | |__________________________________- not an `extern crate` item | = note: read 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:17:16 | LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: read 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:19:11 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items