Skip to content

Commit f2826d9

Browse files
committedSep 5, 2020
Show the first path segment which failed to resolve.
Before, it would arbitrarily pick the third-to-last if the last three or more did not resolve.
1 parent bb9d157 commit f2826d9

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed
 

‎src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,35 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
156156
.ok_or(ErrorKind::Resolve(ResolutionFailure::NotInScope(
157157
variant_name.to_string().into(),
158158
)))?;
159-
let (_, ty_res) = cx
159+
let ty_res = cx
160160
.enter_resolver(|resolver| {
161161
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
162162
})
163-
.map_err(|_| {
164-
ErrorKind::Resolve(ResolutionFailure::NotInScope(path.to_string().into()))
165-
})?;
163+
.map(|(_, res)| res)
164+
.unwrap_or(Res::Err);
165+
// This code only gets hit if three path segments in a row don't get resolved.
166+
// It's a good time to check if _any_ parent of the path gets resolved.
167+
// If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
166168
if let Res::Err = ty_res {
167-
return Err(ErrorKind::Resolve(ResolutionFailure::NotInScope(path.to_string().into())));
169+
let mut current = path.as_str();
170+
while let Some(parent) = current.rsplitn(2, "::").nth(1) {
171+
current = parent;
172+
if let Some(res) = self.check_full_res(
173+
TypeNS,
174+
&current,
175+
Some(module_id),
176+
current_item,
177+
extra_fragment,
178+
) {
179+
return Err(ErrorKind::Resolve(ResolutionFailure::NoAssocItem(
180+
res,
181+
Symbol::intern(&path),
182+
)));
183+
}
184+
}
185+
return Err(ErrorKind::Resolve(ResolutionFailure::NotInScope(
186+
current.to_string().into(),
187+
)));
168188
}
169189
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
170190
match ty_res {

‎src/test/rustdoc-ui/intra-link-errors.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
// FIXME: this should say that it was skipped (maybe an allowed by default lint?)
55
/// [<invalid syntax>]
66
7-
// FIXME: this could say which path was the first to not be found (in this case, `path`)
87
/// [path::to::nonexistent::module]
98
//~^ ERROR unresolved link
10-
//~| NOTE no item named `path::to` is in scope
9+
//~| NOTE no item named `path` is in scope
1110
//~| HELP to escape
1211

1312
/// [std::io::not::here]
@@ -44,7 +43,7 @@
4443

4544
/// [S!]
4645
//~^ ERROR unresolved link
47-
//~| HELP to link to the struct, use its disambiguator
46+
//~| HELP to link to the struct, prefix with the item kind
4847
//~| NOTE this link resolves to the struct `S`
4948
pub fn f() {}
5049
#[derive(Debug)]

‎src/test/rustdoc-ui/intra-link-errors.stderr

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: the lint level is defined here
99
|
1010
LL | #![deny(broken_intra_doc_links)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^
12-
= note: no item named `path::to` is in scope
12+
= note: no item named `path` is in scope
1313
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
1414

1515
error: unresolved link to `std::io::not::here`
@@ -80,15 +80,19 @@ error: unresolved link to `S`
8080
--> $DIR/intra-link-errors.rs:45:6
8181
|
8282
LL | /// [S!]
83-
| ^^ help: to link to the struct, use its disambiguator: `struct@S`
83+
| ^^
8484
|
8585
= note: this link resolves to the struct `S`, which is not in the macro namespace
86+
help: to link to the struct, prefix with the item kind
87+
|
88+
LL | /// [struct@S]
89+
| ^^^^^^^^
8690

8791
error: unresolved link to `T::g`
8892
--> $DIR/intra-link-errors.rs:63:6
8993
|
9094
LL | /// [type@T::g]
91-
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `T::g()`
95+
| ^^^^^^^^^ help: to link to the associated function, add parentheses: `T::g()`
9296
|
9397
= note: this link resolves to the associated function `g`, which is not in the type namespace
9498

@@ -105,15 +109,15 @@ error: unresolved link to `S::h`
105109
--> $DIR/intra-link-errors.rs:55:6
106110
|
107111
LL | /// [type@S::h]
108-
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `S::h()`
112+
| ^^^^^^^^^ help: to link to the associated function, add parentheses: `S::h()`
109113
|
110114
= note: this link resolves to the associated function `h`, which is not in the type namespace
111115

112116
error: unresolved link to `m`
113117
--> $DIR/intra-link-errors.rs:76:6
114118
|
115119
LL | /// [m()]
116-
| ^^^ help: to link to the macro, use its disambiguator: `m!`
120+
| ^^^ help: to link to the macro, add an exclamation mark: `m!`
117121
|
118122
= note: this link resolves to the macro `m`, which is not in the value namespace
119123

0 commit comments

Comments
 (0)