Skip to content

Commit 9c8c67b

Browse files
Fix warning messages
1 parent 976d454 commit 9c8c67b

21 files changed

+377
-135
lines changed

compiler/rustc_attr_parsing/src/attributes/doc.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#![allow(unused_imports)]
33

44
use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit};
5-
use rustc_errors::MultiSpan;
65
use rustc_feature::template;
76
use rustc_hir::attrs::{
87
AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow,
@@ -18,7 +17,7 @@ use crate::fluent_generated as fluent;
1817
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, PathParser};
1918
use crate::session_diagnostics::{
2019
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttributeNotAttribute,
21-
DocKeywordConflict, DocKeywordNotKeyword,
20+
DocKeywordNotKeyword,
2221
};
2322

2423
fn check_keyword<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, keyword: Symbol, span: Span) -> bool {
@@ -204,19 +203,7 @@ impl DocParser {
204203
return;
205204
}
206205

207-
let span = path.span();
208-
209-
if let Some((prev_inline, prev_span)) = self.attribute.inline {
210-
if prev_inline == inline {
211-
let mut spans = MultiSpan::from_spans(vec![prev_span, span]);
212-
spans.push_span_label(prev_span, fluent::attr_parsing_doc_inline_conflict_first);
213-
spans.push_span_label(span, fluent::attr_parsing_doc_inline_conflict_second);
214-
cx.emit_err(DocKeywordConflict { spans });
215-
return;
216-
}
217-
}
218-
219-
self.attribute.inline = Some((inline, span));
206+
self.attribute.inline.push((inline, path.span()));
220207
}
221208

222209
fn parse_cfg<'c, S: Stage>(

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_ast::{self as ast};
44
use rustc_errors::codes::*;
55
use rustc_errors::{
66
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
7-
MultiSpan,
87
};
98
use rustc_feature::AttributeTemplate;
109
use rustc_hir::AttrPath;
@@ -589,14 +588,6 @@ pub(crate) struct DocAliasDuplicated {
589588
pub first_defn: Span,
590589
}
591590

592-
#[derive(Diagnostic)]
593-
#[diag(attr_parsing_doc_inline_conflict)]
594-
#[help]
595-
pub(crate) struct DocKeywordConflict {
596-
#[primary_span]
597-
pub spans: MultiSpan,
598-
}
599-
600591
#[derive(Diagnostic)]
601592
#[diag(attr_parsing_link_ordinal_out_of_range)]
602593
#[note]

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,9 @@ pub struct CfgHideShow {
476476
pub struct DocAttribute {
477477
pub aliases: FxIndexMap<Symbol, Span>,
478478
pub hidden: Option<Span>,
479-
pub inline: Option<(DocInline, Span)>,
479+
// Because we need to emit the error if there is more than one `inline` attribute on an item
480+
// at the same time as the other doc attributes, we store a list instead of using `Option`.
481+
pub inline: ThinVec<(DocInline, Span)>,
480482

481483
// unstable
482484
pub cfg: ThinVec<CfgEntry>,
@@ -511,7 +513,7 @@ impl Default for DocAttribute {
511513
Self {
512514
aliases: FxIndexMap::default(),
513515
hidden: None,
514-
inline: None,
516+
inline: ThinVec::new(),
515517
cfg: ThinVec::new(),
516518
auto_cfg: ThinVec::new(),
517519
auto_cfg_change: ThinVec::new(),

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState<'_>) -> bool
880880
} else if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr {
881881
// If this is a `doc` attribute that doesn't have anything except maybe `inline` (as in
882882
// `#[doc(inline)]`), then we can remove it. It won't be inlinable in downstream crates.
883-
if d.inline.is_none() {
883+
if d.inline.is_empty() {
884884
should_encode = true;
885885
if d.hidden.is_some() {
886886
state.is_doc_hidden = true;

compiler/rustc_passes/messages.ftl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,18 +107,26 @@ passes_diagnostic_item_first_defined =
107107
the diagnostic item is first defined here
108108
109109
passes_doc_alias_bad_location =
110-
doc alias attribute isn't allowed on {$location}
110+
`#[doc(alias = "...")]` isn't allowed on {$location}
111111
112112
passes_doc_alias_not_an_alias =
113-
{$attr_str} is the same as the item's name
113+
`#[doc(alias = "{$attr_str}"]` is the same as the item's name
114114
115115
passes_doc_attr_not_crate_level =
116116
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
117117
118118
passes_doc_fake_variadic_not_valid =
119119
`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
120120
121+
passes_doc_inline_conflict =
122+
conflicting doc inlining attributes
123+
.help = remove one of the conflicting attributes
121124
125+
passes_doc_inline_conflict_first =
126+
this attribute...
127+
128+
passes_doc_inline_conflict_second =
129+
{"."}..conflicts with this attribute
122130
123131
passes_doc_inline_only_use =
124132
this attribute can only be applied to a `use` item

compiler/rustc_passes/src/check_attr.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ use rustc_abi::{Align, ExternAbi, Size};
1313
use rustc_ast::{AttrStyle, LitKind, MetaItemKind, ast};
1414
use rustc_attr_parsing::{AttributeParser, Late};
1515
use rustc_data_structures::fx::FxHashMap;
16-
use rustc_errors::{DiagCtxtHandle, IntoDiagArg, StashKey};
16+
use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
1717
use rustc_feature::{
1818
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
1919
BuiltinAttribute,
2020
};
2121
use rustc_hir::attrs::{
22-
AttributeKind, DocAttribute, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet,
22+
AttributeKind, DocAttribute, DocInline, InlineAttr, MirDialect, MirPhase, ReprAttr,
23+
SanitizerSet,
2324
};
2425
use rustc_hir::def::DefKind;
2526
use rustc_hir::def_id::LocalModDefId;
@@ -881,7 +882,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
881882
/// already seen an inlining attribute for this item.
882883
/// If so, `specified_inline` holds the value and the span of
883884
/// the first `inline`/`no_inline` attribute.
884-
fn check_doc_inline(&self, span: Span, hir_id: HirId, target: Target) {
885+
fn check_doc_inline(&self, hir_id: HirId, target: Target, inline: &[(DocInline, Span)]) {
886+
let span = match inline {
887+
[] => return,
888+
[(_, span)] => *span,
889+
[(inline, span), rest @ ..] => {
890+
for (inline2, span2) in rest {
891+
if inline2 != inline {
892+
let mut spans = MultiSpan::from_spans(vec![*span, *span2]);
893+
spans.push_span_label(*span, fluent::passes_doc_inline_conflict_first);
894+
spans.push_span_label(*span2, fluent::passes_doc_inline_conflict_second);
895+
self.dcx().emit_err(errors::DocInlineConflict { spans });
896+
return;
897+
}
898+
}
899+
*span
900+
}
901+
};
902+
885903
match target {
886904
Target::Use | Target::ExternCrate => {}
887905
_ => {
@@ -1050,9 +1068,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
10501068
}
10511069
}
10521070

1053-
if let Some((_, span)) = inline {
1054-
self.check_doc_inline(*span, hir_id, target)
1055-
}
1071+
self.check_doc_inline(hir_id, target, inline);
10561072

10571073
if let Some(span) = rust_logo {
10581074
if self.check_attr_crate_level(*span, hir_id)

compiler/rustc_passes/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ pub(crate) struct DocSearchUnboxInvalid {
176176
pub span: Span,
177177
}
178178

179+
#[derive(Diagnostic)]
180+
#[diag(passes_doc_inline_conflict)]
181+
#[help]
182+
pub(crate) struct DocInlineConflict {
183+
#[primary_span]
184+
pub spans: MultiSpan,
185+
}
186+
179187
#[derive(LintDiagnostic)]
180188
#[diag(passes_doc_inline_only_use)]
181189
#[note]

src/librustdoc/clean/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ fn generate_item_with_correct_attrs(
199199
let import_is_inline = find_attr!(
200200
inline::load_attrs(cx, import_id.to_def_id()),
201201
AttributeKind::Doc(d)
202-
if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline)
202+
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
203203
) || (is_glob_import(cx.tcx, import_id)
204204
&& (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id)));
205205
attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
@@ -2921,7 +2921,7 @@ fn clean_extern_crate<'tcx>(
29212921
matches!(
29222922
a,
29232923
hir::Attribute::Parsed(AttributeKind::Doc(d))
2924-
if d.inline.is_some_and(|(i, _)| i == DocInline::Inline))
2924+
if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline))
29252925
})
29262926
&& !cx.is_json_output();
29272927

@@ -2986,9 +2986,9 @@ fn clean_use_statement_inner<'tcx>(
29862986
let attrs = cx.tcx.hir_attrs(import.hir_id());
29872987
let inline_attr = find_attr!(
29882988
attrs,
2989-
AttributeKind::Doc(d) if d.inline.is_some_and(|(i, _)| i == DocInline::Inline) => d
2989+
AttributeKind::Doc(d) if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline) => d
29902990
)
2991-
.and_then(|d| d.inline);
2991+
.and_then(|d| d.inline.first());
29922992
let pub_underscore = visibility.is_public() && name == Some(kw::Underscore);
29932993
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
29942994
let import_def_id = import.owner_id.def_id;
@@ -3009,7 +3009,7 @@ fn clean_use_statement_inner<'tcx>(
30093009
if pub_underscore && let Some((_, inline_span)) = inline_attr {
30103010
struct_span_code_err!(
30113011
cx.tcx.dcx(),
3012-
inline_span,
3012+
*inline_span,
30133013
E0780,
30143014
"anonymous imports cannot be inlined"
30153015
)
@@ -3026,7 +3026,9 @@ fn clean_use_statement_inner<'tcx>(
30263026
|| pub_underscore
30273027
|| attrs.iter().any(|a| matches!(
30283028
a,
3029-
hir::Attribute::Parsed(AttributeKind::Doc(d)) if d.hidden.is_some() || d.inline.is_some_and(|(i, _)| i == DocInline::NoInline)));
3029+
hir::Attribute::Parsed(AttributeKind::Doc(d))
3030+
if d.hidden.is_some() || d.inline.first().is_some_and(|(i, _)| *i == DocInline::NoInline)
3031+
));
30303032

30313033
// Also check whether imports were asked to be inlined, in case we're trying to re-export a
30323034
// crate in Rust 2018+

src/librustdoc/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
extern crate rustc_abi;
3333
extern crate rustc_ast;
3434
extern crate rustc_ast_pretty;
35+
extern crate rustc_attr_parsing;
3536
extern crate rustc_data_structures;
3637
extern crate rustc_driver;
3738
extern crate rustc_errors;
@@ -75,6 +76,7 @@ use std::process;
7576

7677
use rustc_errors::DiagCtxtHandle;
7778
use rustc_hir::def_id::LOCAL_CRATE;
79+
use rustc_hir::lints::DelayedLint;
7880
use rustc_interface::interface;
7981
use rustc_middle::ty::TyCtxt;
8082
use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@@ -900,6 +902,18 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
900902
return;
901903
}
902904

905+
for owner_id in tcx.hir_crate_items(()).delayed_lint_items() {
906+
if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
907+
for lint in &delayed_lints.lints {
908+
match lint {
909+
DelayedLint::AttributeParsing(attribute_lint) => {
910+
rustc_attr_parsing::emit_attribute_lint(attribute_lint, tcx)
911+
}
912+
}
913+
}
914+
}
915+
}
916+
903917
if render_opts.dep_info().is_some() {
904918
rustc_interface::passes::write_dep_info(tcx);
905919
}

src/librustdoc/visit_ast.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
247247
let document_hidden = self.cx.document_hidden();
248248
let use_attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
249249
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
250-
let is_no_inline = find_attr!(use_attrs, AttributeKind::Doc(d) if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline))
251-
|| (document_hidden && use_attrs.iter().any(|attr| attr.is_doc_hidden()));
250+
let is_no_inline = find_attr!(
251+
use_attrs,
252+
AttributeKind::Doc(d)
253+
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::NoInline)
254+
) || (document_hidden
255+
&& use_attrs.iter().any(|attr| attr.is_doc_hidden()));
252256

253257
if is_no_inline {
254258
return false;
@@ -465,7 +469,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
465469
// If there was a private module in the current path then don't bother inlining
466470
// anything as it will probably be stripped anyway.
467471
if is_pub && self.inside_public_path {
468-
let please_inline = find_attr!(attrs, AttributeKind::Doc(d) if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline));
472+
let please_inline = find_attr!(
473+
attrs,
474+
AttributeKind::Doc(d)
475+
if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline)
476+
);
469477
let ident = match kind {
470478
hir::UseKind::Single(ident) => Some(ident.name),
471479
hir::UseKind::Glob => None,

0 commit comments

Comments
 (0)