Skip to content

Commit 7e683cc

Browse files
Do not emit redundant_explicit_links rustdoc lint if the doc comment comes from expansion
1 parent 22be76b commit 7e683cc

File tree

7 files changed

+100
-54
lines changed

7 files changed

+100
-54
lines changed

compiler/rustc_resolve/src/rustdoc.rs

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ pub struct DocFragment {
4949
pub doc: Symbol,
5050
pub kind: DocFragmentKind,
5151
pub indent: usize,
52+
/// Because we temper with the spans context, this information cannot be correctly retrieved
53+
/// later on. So instead, we compute it and store it here.
54+
pub from_expansion: bool,
5255
}
5356

5457
#[derive(Clone, Copy, Debug)]
@@ -208,17 +211,18 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
208211
for (attr, item_id) in attrs {
209212
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
210213
let doc = beautify_doc_string(doc_str, comment_kind);
211-
let (span, kind) = if attr.is_doc_comment() {
212-
(attr.span(), DocFragmentKind::SugaredDoc)
214+
let (span, kind, from_expansion) = if attr.is_doc_comment() {
215+
let span = attr.span();
216+
(span, DocFragmentKind::SugaredDoc, span.from_expansion())
213217
} else {
214-
(
215-
attr.value_span()
216-
.map(|i| i.with_ctxt(attr.span().ctxt()))
217-
.unwrap_or(attr.span()),
218-
DocFragmentKind::RawDoc,
219-
)
218+
let attr_span = attr.span();
219+
let (span, from_expansion) = match attr.value_span() {
220+
Some(sp) => (sp.with_ctxt(attr_span.ctxt()), sp.from_expansion()),
221+
None => (attr_span, attr_span.from_expansion()),
222+
};
223+
(span, DocFragmentKind::RawDoc, from_expansion)
220224
};
221-
let fragment = DocFragment { span, doc, kind, item_id, indent: 0 };
225+
let fragment = DocFragment { span, doc, kind, item_id, indent: 0, from_expansion };
222226
doc_fragments.push(fragment);
223227
} else if !doc_only {
224228
other_attrs.push(attr.clone());
@@ -506,16 +510,21 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>(
506510
}
507511

508512
/// Returns a span encompassing all the document fragments.
509-
pub fn span_of_fragments(fragments: &[DocFragment]) -> Option<Span> {
510-
if fragments.is_empty() {
511-
return None;
512-
}
513-
let start = fragments[0].span;
514-
if start == DUMMY_SP {
513+
pub fn span_of_fragments_with_expansion(fragments: &[DocFragment]) -> Option<(Span, bool)> {
514+
let Some(first_fragment) = fragments.first() else { return None };
515+
if first_fragment.span == DUMMY_SP {
515516
return None;
516517
}
517-
let end = fragments.last().expect("no doc strings provided").span;
518-
Some(start.to(end))
518+
let last_fragment = fragments.last().expect("no doc strings provided");
519+
Some((
520+
first_fragment.span.to(last_fragment.span),
521+
first_fragment.from_expansion || last_fragment.from_expansion,
522+
))
523+
}
524+
525+
/// Returns a span encompassing all the document fragments.
526+
pub fn span_of_fragments(fragments: &[DocFragment]) -> Option<Span> {
527+
span_of_fragments_with_expansion(fragments).map(|(sp, _)| sp)
519528
}
520529

521530
/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -540,7 +549,7 @@ pub fn source_span_for_markdown_range(
540549
markdown: &str,
541550
md_range: &Range<usize>,
542551
fragments: &[DocFragment],
543-
) -> Option<Span> {
552+
) -> Option<(Span, bool)> {
544553
let map = tcx.sess.source_map();
545554
source_span_for_markdown_range_inner(map, markdown, md_range, fragments)
546555
}
@@ -551,7 +560,7 @@ pub fn source_span_for_markdown_range_inner(
551560
markdown: &str,
552561
md_range: &Range<usize>,
553562
fragments: &[DocFragment],
554-
) -> Option<Span> {
563+
) -> Option<(Span, bool)> {
555564
use rustc_span::BytePos;
556565

557566
if let &[fragment] = &fragments
@@ -562,11 +571,14 @@ pub fn source_span_for_markdown_range_inner(
562571
&& let Ok(md_range_hi) = u32::try_from(md_range.end)
563572
{
564573
// Single fragment with string that contains same bytes as doc.
565-
return Some(Span::new(
566-
fragment.span.lo() + rustc_span::BytePos(md_range_lo),
567-
fragment.span.lo() + rustc_span::BytePos(md_range_hi),
568-
fragment.span.ctxt(),
569-
fragment.span.parent(),
574+
return Some((
575+
Span::new(
576+
fragment.span.lo() + rustc_span::BytePos(md_range_lo),
577+
fragment.span.lo() + rustc_span::BytePos(md_range_hi),
578+
fragment.span.ctxt(),
579+
fragment.span.parent(),
580+
),
581+
fragment.from_expansion,
570582
));
571583
}
572584

@@ -598,19 +610,21 @@ pub fn source_span_for_markdown_range_inner(
598610
{
599611
match_data = Some((i, match_start));
600612
} else {
601-
// Heirustic produced ambiguity, return nothing.
613+
// Heuristic produced ambiguity, return nothing.
602614
return None;
603615
}
604616
}
605617
}
606618
if let Some((i, match_start)) = match_data {
607-
let sp = fragments[i].span;
619+
let fragment = &fragments[i];
620+
let sp = fragment.span;
608621
// we need to calculate the span start,
609622
// then use that in our calulations for the span end
610623
let lo = sp.lo() + BytePos(match_start as u32);
611-
return Some(
624+
return Some((
612625
sp.with_lo(lo).with_hi(lo + BytePos((md_range.end - md_range.start) as u32)),
613-
);
626+
fragment.from_expansion,
627+
));
614628
}
615629
return None;
616630
}
@@ -664,8 +678,12 @@ pub fn source_span_for_markdown_range_inner(
664678
}
665679
}
666680

667-
Some(span_of_fragments(fragments)?.from_inner(InnerSpan::new(
668-
md_range.start + start_bytes,
669-
md_range.end + start_bytes + end_bytes,
670-
)))
681+
let (span, from_expansion) = span_of_fragments_with_expansion(fragments)?;
682+
Some((
683+
span.from_inner(InnerSpan::new(
684+
md_range.start + start_bytes,
685+
md_range.end + start_bytes + end_bytes,
686+
)),
687+
from_expansion,
688+
))
671689
}

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,13 +1387,15 @@ impl LinkCollector<'_, '_> {
13871387
ori_link: &MarkdownLinkRange,
13881388
item: &Item,
13891389
) {
1390-
let span = source_span_for_markdown_range(
1390+
let span = match source_span_for_markdown_range(
13911391
self.cx.tcx,
13921392
dox,
13931393
ori_link.inner_range(),
13941394
&item.attrs.doc_strings,
1395-
)
1396-
.unwrap_or_else(|| item.attr_span(self.cx.tcx));
1395+
) {
1396+
Some((sp, _)) => sp,
1397+
None => item.attr_span(self.cx.tcx),
1398+
};
13971399
rustc_session::parse::feature_err(
13981400
self.cx.tcx.sess,
13991401
sym::intra_doc_pointers,
@@ -1836,7 +1838,7 @@ fn report_diagnostic(
18361838
let mut md_range = md_range.clone();
18371839
let sp =
18381840
source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs.doc_strings)
1839-
.map(|mut sp| {
1841+
.map(|(mut sp, _)| {
18401842
while dox.as_bytes().get(md_range.start) == Some(&b' ')
18411843
|| dox.as_bytes().get(md_range.start) == Some(&b'`')
18421844
{
@@ -1854,7 +1856,8 @@ fn report_diagnostic(
18541856
(sp, MarkdownLinkRange::Destination(md_range))
18551857
}
18561858
MarkdownLinkRange::WholeLink(md_range) => (
1857-
source_span_for_markdown_range(tcx, dox, md_range, &item.attrs.doc_strings),
1859+
source_span_for_markdown_range(tcx, dox, md_range, &item.attrs.doc_strings)
1860+
.map(|(sp, _)| sp),
18581861
link_range.clone(),
18591862
),
18601863
};

src/librustdoc/passes/lint/bare_urls.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use crate::html::markdown::main_body_opts;
1818

1919
pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) {
2020
let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range<usize>| {
21-
let maybe_sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings);
21+
let maybe_sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings)
22+
.map(|(sp, _)| sp);
2223
let sp = maybe_sp.unwrap_or_else(|| item.attr_span(cx.tcx));
2324
cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| {
2425
lint.primary_message(msg)

src/librustdoc/passes/lint/check_code_block_syntax.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn check_rust_syntax(
8787
&code_block.range,
8888
&item.attrs.doc_strings,
8989
) {
90-
Some(sp) => (sp, true),
90+
Some((sp, _)) => (sp, true),
9191
None => (item.attr_span(cx.tcx), false),
9292
};
9393

src/librustdoc/passes/lint/html_tags.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
1616
let tcx = cx.tcx;
1717
let report_diag = |msg: String, range: &Range<usize>, is_open_tag: bool| {
1818
let sp = match source_span_for_markdown_range(tcx, dox, range, &item.attrs.doc_strings) {
19-
Some(sp) => sp,
19+
Some((sp, _)) => sp,
2020
None => item.attr_span(tcx),
2121
};
2222
tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
@@ -55,7 +55,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
5555
&(generics_start..generics_end),
5656
&item.attrs.doc_strings,
5757
) {
58-
Some(sp) => sp,
58+
Some((sp, _)) => sp,
5959
None => item.attr_span(tcx),
6060
};
6161
// Sometimes, we only extract part of a path. For example, consider this:

src/librustdoc/passes/lint/redundant_explicit_links.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,26 @@ fn check_inline_or_reference_unknown_redundancy(
161161

162162
if dest_res == display_res {
163163
let link_span =
164-
source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings)
165-
.unwrap_or(item.attr_span(cx.tcx));
166-
let explicit_span = source_span_for_markdown_range(
164+
match source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings)
165+
{
166+
Some((sp, from_expansion)) => {
167+
if from_expansion {
168+
return None;
169+
}
170+
sp
171+
}
172+
None => item.attr_span(cx.tcx),
173+
};
174+
let (explicit_span, from_expansion) = source_span_for_markdown_range(
167175
cx.tcx,
168176
doc,
169177
&offset_explicit_range(doc, link_range, open, close),
170178
&item.attrs.doc_strings,
171179
)?;
172-
let display_span = source_span_for_markdown_range(
180+
if from_expansion {
181+
return None;
182+
}
183+
let (display_span, _) = source_span_for_markdown_range(
173184
cx.tcx,
174185
doc,
175186
resolvable_link_range,
@@ -206,21 +217,32 @@ fn check_reference_redundancy(
206217

207218
if dest_res == display_res {
208219
let link_span =
209-
source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings)
210-
.unwrap_or(item.attr_span(cx.tcx));
211-
let explicit_span = source_span_for_markdown_range(
220+
match source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings)
221+
{
222+
Some((sp, from_expansion)) => {
223+
if from_expansion {
224+
return None;
225+
}
226+
sp
227+
}
228+
None => item.attr_span(cx.tcx),
229+
};
230+
let (explicit_span, from_expansion) = source_span_for_markdown_range(
212231
cx.tcx,
213232
doc,
214233
&offset_explicit_range(doc, link_range.clone(), b'[', b']'),
215234
&item.attrs.doc_strings,
216235
)?;
217-
let display_span = source_span_for_markdown_range(
236+
if from_expansion {
237+
return None;
238+
}
239+
let (display_span, _) = source_span_for_markdown_range(
218240
cx.tcx,
219241
doc,
220242
resolvable_link_range,
221243
&item.attrs.doc_strings,
222244
)?;
223-
let def_span = source_span_for_markdown_range(
245+
let (def_span, _) = source_span_for_markdown_range(
224246
cx.tcx,
225247
doc,
226248
&offset_reference_def_range(doc, dest, link_range),

src/librustdoc/passes/lint/unescaped_backticks.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
4242

4343
// If we can't get a span of the backtick, because it is in a `#[doc = ""]` attribute,
4444
// use the span of the entire attribute as a fallback.
45-
let span = source_span_for_markdown_range(
45+
let span = match source_span_for_markdown_range(
4646
tcx,
4747
dox,
4848
&(backtick_index..backtick_index + 1),
4949
&item.attrs.doc_strings,
50-
)
51-
.unwrap_or_else(|| item.attr_span(tcx));
50+
) {
51+
Some((sp, _)) => sp,
52+
None => item.attr_span(tcx),
53+
};
5254

5355
tcx.node_span_lint(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, |lint| {
5456
lint.primary_message("unescaped backtick");
@@ -419,7 +421,7 @@ fn suggest_insertion(
419421
/// Maximum bytes of context to show around the insertion.
420422
const CONTEXT_MAX_LEN: usize = 80;
421423

422-
if let Some(span) = source_span_for_markdown_range(
424+
if let Some((span, _)) = source_span_for_markdown_range(
423425
cx.tcx,
424426
dox,
425427
&(insert_index..insert_index),

0 commit comments

Comments
 (0)