Skip to content

Commit 5ce6cc7

Browse files
committed
Still resolving rustdoc resolution panicking
1 parent 46df958 commit 5ce6cc7

File tree

10 files changed

+90
-80
lines changed

10 files changed

+90
-80
lines changed

compiler/rustc_resolve/src/rustdoc.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,10 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
410410
while let Some(event) = event_iter.next() {
411411
match event {
412412
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
413-
if let Some(display_text) = collect_link_data(&mut event_iter) {
414-
links.push(display_text);
413+
if matches!(link_type, LinkType::Inline | LinkType::ReferenceUnknown | LinkType::Reference) {
414+
if let Some(display_text) = collect_link_data(&mut event_iter) {
415+
links.push(display_text);
416+
}
415417
}
416418

417419
links.push(preprocess_link(&dest));

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ impl LinkCollector<'_, '_> {
10381038
// resolutions are cached, for other links we want to report an error every
10391039
// time so they are not cached.
10401040
matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
1041+
false,
10411042
)?;
10421043

10431044
self.resolve_display_text(
@@ -1232,14 +1233,17 @@ impl LinkCollector<'_, '_> {
12321233
// If errors are cached then they are only reported on first occurrence
12331234
// which we want in some cases but not in others.
12341235
cache_errors: bool,
1236+
// If this call is intended to be recoverable, then pass true to silence.
1237+
// This is only recoverable when path is failed to resolved.
1238+
recoverable: bool,
12351239
) -> Option<(Res, Option<UrlFragment>)> {
12361240
if let Some(res) = self.visited_links.get(&key) {
12371241
if res.is_some() || cache_errors {
12381242
return res.clone();
12391243
}
12401244
}
12411245

1242-
let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
1246+
let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
12431247

12441248
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
12451249
// However I'm not sure how to check that across crates.
@@ -1290,6 +1294,9 @@ impl LinkCollector<'_, '_> {
12901294
&mut self,
12911295
key: &ResolutionInfo,
12921296
diag: DiagnosticInfo<'_>,
1297+
// If this call is intended to be recoverable, then pass true to silence.
1298+
// This is only recoverable when path is failed to resolved.
1299+
recoverable: bool,
12931300
) -> Vec<(Res, Option<DefId>)> {
12941301
let disambiguator = key.dis;
12951302
let path_str = &key.path_str;
@@ -1319,7 +1326,9 @@ impl LinkCollector<'_, '_> {
13191326
}
13201327
}
13211328
}
1322-
resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
1329+
if !recoverable {
1330+
resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
1331+
}
13231332
return vec![];
13241333
}
13251334
}
@@ -1356,13 +1365,15 @@ impl LinkCollector<'_, '_> {
13561365
.fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
13571366

13581367
if len == 0 {
1359-
resolution_failure(
1360-
self,
1361-
diag,
1362-
path_str,
1363-
disambiguator,
1364-
candidates.into_iter().filter_map(|res| res.err()).collect(),
1365-
);
1368+
if !recoverable {
1369+
resolution_failure(
1370+
self,
1371+
diag,
1372+
path_str,
1373+
disambiguator,
1374+
candidates.into_iter().filter_map(|res| res.err()).collect(),
1375+
);
1376+
}
13661377
return vec![];
13671378
} else if len == 1 {
13681379
candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
@@ -1396,43 +1407,8 @@ impl LinkCollector<'_, '_> {
13961407
ori_link: &MarkdownLink,
13971408
diag_info: &DiagnosticInfo<'_>,
13981409
) {
1399-
// Check if explicit resolution's path is same as resolution of original link's display text path, e.g.
1400-
//
1401-
// LinkType::Inline:
1402-
//
1403-
// [target](target)
1404-
// [`target`](target)
1405-
// [target](path::to::target)
1406-
// [`target`](path::to::target)
1407-
// [path::to::target](target)
1408-
// [`path::to::target`](target)
1409-
// [path::to::target](path::to::target)
1410-
// [`path::to::target`](path::to::target)
1411-
//
1412-
// LinkType::ReferenceUnknown
1413-
//
1414-
// [target][target]
1415-
// [`target`][target]
1416-
// [target][path::to::target]
1417-
// [`target`][path::to::target]
1418-
// [path::to::target][target]
1419-
// [`path::to::target`][target]
1420-
// [path::to::target][path::to::target]
1421-
// [`path::to::target`][path::to::target]
1422-
//
1423-
// LinkType::Reference
1424-
//
1425-
// [target][target]
1426-
// [`target`][target]
1427-
// [target][path::to::target]
1428-
// [`target`][path::to::target]
1429-
// [path::to::target][target]
1430-
// [`path::to::target`][target]
1431-
// [path::to::target][path::to::target]
1432-
// [`path::to::target`][path::to::target]
1433-
//
1434-
// [target]: target // or [target]: path::to::target
1435-
// [path::to::target]: path::to::target // or [path::to::target]: target
1410+
// Check if explicit resolution's path is same as resolution of original link's display text path, see
1411+
// tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
14361412
//
14371413
// To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
14381414
// into explicit path.
@@ -1471,6 +1447,7 @@ impl LinkCollector<'_, '_> {
14711447
display_res_info,
14721448
diag_info.clone(), // this struct should really be Copy, but Range is not :(
14731449
false,
1450+
true,
14741451
);
14751452
}
14761453
}

src/librustdoc/passes/lint/redundant_explicit_links.rs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
3232
return;
3333
}
3434

35+
if item.link_names(&cx.cache).is_empty() {
36+
// If there's no link names in this item,
37+
// then we skip resolution querying to
38+
// avoid from panicking.
39+
return;
40+
}
41+
3542
check_redundant_explicit_link(cx, item, hir_id, &doc);
3643
}
3744

@@ -57,33 +64,52 @@ fn check_redundant_explicit_link<'md>(
5764

5865
while let Some((event, link_range)) = offset_iter.next() {
5966
match event {
60-
Event::Start(Tag::Link(link_type, dest, _)) => match link_type {
61-
LinkType::Inline | LinkType::ReferenceUnknown => {
62-
check_inline_or_reference_unknown_redundancy(
63-
cx,
64-
item,
65-
hir_id,
66-
doc,
67-
resolutions,
68-
link_range,
69-
dest.to_string(),
70-
collect_link_data(&mut offset_iter),
71-
if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') },
72-
);
67+
Event::Start(Tag::Link(link_type, dest, _)) => {
68+
let link_data = collect_link_data(&mut offset_iter);
69+
70+
let explicit_link = dest.to_string();
71+
let display_link = link_data.resolvable_link.clone()?;
72+
let explicit_len = explicit_link.len();
73+
let display_len = display_link.len();
74+
75+
if explicit_len == display_len && explicit_link != display_link {
76+
// Skips if they possibly have no relativity.
77+
continue;
7378
}
74-
LinkType::Reference => {
75-
check_reference_redundancy(
76-
cx,
77-
item,
78-
hir_id,
79-
doc,
80-
resolutions,
81-
link_range,
82-
&dest,
83-
collect_link_data(&mut offset_iter),
84-
);
79+
80+
if (explicit_len >= display_len
81+
&& &explicit_link[(explicit_len - display_len)..] == display_link)
82+
|| (display_len >= explicit_len
83+
&& &display_link[(display_len - explicit_len)..] == explicit_link) {
84+
match link_type {
85+
LinkType::Inline | LinkType::ReferenceUnknown => {
86+
check_inline_or_reference_unknown_redundancy(
87+
cx,
88+
item,
89+
hir_id,
90+
doc,
91+
resolutions,
92+
link_range,
93+
dest.to_string(),
94+
link_data,
95+
if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') },
96+
);
97+
}
98+
LinkType::Reference => {
99+
check_reference_redundancy(
100+
cx,
101+
item,
102+
hir_id,
103+
doc,
104+
resolutions,
105+
link_range,
106+
&dest,
107+
link_data,
108+
);
109+
}
110+
_ => {}
111+
}
85112
}
86-
_ => {}
87113
},
88114
_ => {}
89115
}

tests/rustdoc-ui/lints/redundant_explicit_links.fixed

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn dummy_target() {}
4242
//~^ ERROR redundant explicit link target
4343
/// [`std::primitive::usize`]
4444
//~^ ERROR redundant explicit link target
45-
///
45+
///
4646
/// [dummy_target] TEXT
4747
//~^ ERROR redundant explicit link target
4848
/// [`dummy_target`] TEXT
@@ -91,7 +91,7 @@ pub fn should_not_warn_inline() {}
9191
//~^ ERROR redundant explicit link target
9292
/// [`std::primitive::usize`]
9393
//~^ ERROR redundant explicit link target
94-
///
94+
///
9595
/// [dummy_target] TEXT
9696
//~^ ERROR redundant explicit link target
9797
/// [`dummy_target`] TEXT
@@ -140,7 +140,7 @@ pub fn should_not_warn_reference_unknown() {}
140140
//~^ ERROR redundant explicit link target
141141
/// [`std::primitive::usize`]
142142
//~^ ERROR redundant explicit link target
143-
///
143+
///
144144
/// [dummy_target] TEXT
145145
//~^ ERROR redundant explicit link target
146146
/// [`dummy_target`] TEXT

tests/rustdoc-ui/lints/redundant_explicit_links.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn dummy_target() {}
4242
//~^ ERROR redundant explicit link target
4343
/// [`std::primitive::usize`](std::primitive::usize)
4444
//~^ ERROR redundant explicit link target
45-
///
45+
///
4646
/// [dummy_target](dummy_target) TEXT
4747
//~^ ERROR redundant explicit link target
4848
/// [`dummy_target`](dummy_target) TEXT
@@ -91,7 +91,7 @@ pub fn should_not_warn_inline() {}
9191
//~^ ERROR redundant explicit link target
9292
/// [`std::primitive::usize`][std::primitive::usize]
9393
//~^ ERROR redundant explicit link target
94-
///
94+
///
9595
/// [dummy_target][dummy_target] TEXT
9696
//~^ ERROR redundant explicit link target
9797
/// [`dummy_target`][dummy_target] TEXT
@@ -140,7 +140,7 @@ pub fn should_not_warn_reference_unknown() {}
140140
//~^ ERROR redundant explicit link target
141141
/// [`std::primitive::usize`][std::primitive::usize]
142142
//~^ ERROR redundant explicit link target
143-
///
143+
///
144144
/// [dummy_target][dummy_target] TEXT
145145
//~^ ERROR redundant explicit link target
146146
/// [`dummy_target`][dummy_target] TEXT

tests/rustdoc-ui/unescaped_backticks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![deny(rustdoc::unescaped_backticks)]
22
#![allow(rustdoc::broken_intra_doc_links)]
33
#![allow(rustdoc::invalid_html_tags)]
4+
#![allow(rustdoc::redundant_explicit_links)]
45

56
///
67
pub fn empty() {}

tests/rustdoc/description.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ pub fn foo_fn() {}
2626
// @has 'foo/fn.bar_fn.html' '//meta[@name="description"]/@content' \
2727
// 'Description with intra-doc link to foo_fn and [nonexistent_item] and foo_fn.'
2828
#[allow(rustdoc::broken_intra_doc_links)]
29-
/// Description with intra-doc link to [foo_fn] and [nonexistent_item] and [foo_fn](self::foo_fn).
29+
/// Description with intra-doc link to [foo_fn] and [nonexistent_item] and [foo_fn].
3030
pub fn bar_fn() {}

tests/rustdoc/intra-doc/basic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(rustdoc::redundant_explicit_links)]
2+
13
// @has basic/index.html
24
// @has - '//a/@href' 'struct.ThisType.html'
35
// @has - '//a/@title' 'struct basic::ThisType'

tests/rustdoc/intra-doc/generic-params.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// ignore-tidy-linelength
22

33
#![crate_name = "foo"]
4+
#![allow(rustdoc::redundant_explicit_links)]
45

56
//! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
67
//! Here's a link to [`Iterator<Box<T>>::Item`].

tests/rustdoc/intra-doc/issue-108459.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![deny(rustdoc::broken_intra_doc_links)]
2+
#![allow(rustdoc::redundant_explicit_links)]
23

34
pub struct S;
45
pub mod char {}

0 commit comments

Comments
 (0)