Skip to content

Commit 26fb306

Browse files
Emit error for ambiguities still not resolved at later stage
1 parent 524a9fb commit 26fb306

File tree

5 files changed

+107
-14
lines changed

5 files changed

+107
-14
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+43-14
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ pub(crate) struct ResolutionInfo {
249249
extra_fragment: Option<String>,
250250
}
251251

252-
#[derive(Clone)]
252+
#[derive(Clone, Debug)]
253253
pub(crate) struct DiagnosticInfo<'a> {
254254
item: &'a Item,
255255
dox: &'a str,
@@ -259,6 +259,7 @@ pub(crate) struct DiagnosticInfo<'a> {
259259

260260
pub(crate) struct OwnedDiagnosticInfo {
261261
item: Item,
262+
dox: String,
262263
ori_link: String,
263264
link_range: MarkdownLinkRange,
264265
}
@@ -267,6 +268,7 @@ impl From<DiagnosticInfo<'_>> for OwnedDiagnosticInfo {
267268
fn from(f: DiagnosticInfo<'_>) -> Self {
268269
Self {
269270
item: f.item.clone(),
271+
dox: f.dox.to_string(),
270272
ori_link: f.ori_link.to_string(),
271273
link_range: f.link_range.clone(),
272274
}
@@ -278,7 +280,7 @@ impl OwnedDiagnosticInfo {
278280
DiagnosticInfo {
279281
item: &self.item,
280282
ori_link: &self.ori_link,
281-
dox: "",
283+
dox: &self.dox,
282284
link_range: self.link_range.clone(),
283285
}
284286
}
@@ -1156,18 +1158,45 @@ impl LinkCollector<'_, '_> {
11561158
// Primitive types are always valid.
11571159
Res::Primitive(_) => true,
11581160
});
1159-
if info.resolved.len() == 1 {
1160-
let (res, fragment) = info.resolved.pop().unwrap();
1161-
let diag_info = info.diag_info.into_info();
1162-
if let Some(link) = self.compute_link(
1163-
res,
1164-
fragment,
1165-
path_str,
1166-
info.disambiguator,
1167-
diag_info,
1168-
&info.link_text,
1169-
) {
1170-
self.save_link(*item_id, link);
1161+
let diag_info = info.diag_info.into_info();
1162+
match info.resolved.len() {
1163+
1 => {
1164+
let (res, fragment) = info.resolved.pop().unwrap();
1165+
if let Some(link) = self.compute_link(
1166+
res,
1167+
fragment,
1168+
path_str,
1169+
info.disambiguator,
1170+
diag_info,
1171+
&info.link_text,
1172+
) {
1173+
self.save_link(*item_id, link);
1174+
}
1175+
}
1176+
0 => {
1177+
report_diagnostic(
1178+
self.cx.tcx,
1179+
BROKEN_INTRA_DOC_LINKS,
1180+
format!(
1181+
"all items matching `{path_str}` are either private or doc(hidden)"
1182+
),
1183+
&diag_info,
1184+
|diag, sp, _| {
1185+
if let Some(sp) = sp {
1186+
diag.span_label(sp, "unresolved link");
1187+
} else {
1188+
diag.note("unresolved link");
1189+
}
1190+
},
1191+
);
1192+
}
1193+
_ => {
1194+
let candidates = info
1195+
.resolved
1196+
.iter()
1197+
.map(|(res, _)| (*res, res.def_id(self.cx.tcx)))
1198+
.collect::<Vec<_>>();
1199+
ambiguity_error(self.cx, &diag_info, path_str, &candidates, true);
11711200
}
11721201
}
11731202
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This test ensures that ambiguities (not) resolved at a later stage still emit an error.
2+
3+
#![deny(rustdoc::broken_intra_doc_links)]
4+
#![crate_name = "foo"]
5+
6+
#[doc(hidden)]
7+
pub struct Thing {}
8+
9+
#[allow(non_snake_case)]
10+
#[doc(hidden)]
11+
pub fn Thing() {}
12+
13+
/// Do stuff with [`Thing`].
14+
//~^ ERROR all items matching `Thing` are either private or doc(hidden)
15+
pub fn repro(_: Thing) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: all items matching `Thing` are either private or doc(hidden)
2+
--> $DIR/filter-out-private-2.rs:13:21
3+
|
4+
LL | /// Do stuff with [`Thing`].
5+
| ^^^^^ unresolved link
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/filter-out-private-2.rs:3:9
9+
|
10+
LL | #![deny(rustdoc::broken_intra_doc_links)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 1 previous error
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This test ensures that ambiguities resolved at a later stage still emit an error.
2+
3+
#![deny(rustdoc::broken_intra_doc_links)]
4+
#![crate_name = "foo"]
5+
6+
pub struct Thing {}
7+
8+
#[allow(non_snake_case)]
9+
pub fn Thing() {}
10+
11+
/// Do stuff with [`Thing`].
12+
//~^ ERROR `Thing` is both a function and a struct
13+
pub fn repro(_: Thing) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: `Thing` is both a function and a struct
2+
--> $DIR/filter-out-private.rs:11:21
3+
|
4+
LL | /// Do stuff with [`Thing`].
5+
| ^^^^^ ambiguous link
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/filter-out-private.rs:3:9
9+
|
10+
LL | #![deny(rustdoc::broken_intra_doc_links)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
help: to link to the function, add parentheses
13+
|
14+
LL | /// Do stuff with [`Thing()`].
15+
| ++
16+
help: to link to the struct, prefix with `struct@`
17+
|
18+
LL | /// Do stuff with [`struct@Thing`].
19+
| +++++++
20+
21+
error: aborting due to 1 previous error
22+

0 commit comments

Comments
 (0)