Skip to content

Commit 1c5cef9

Browse files
committed
small code improvements in collect_intra_doc_links
1 parent b6ab01a commit 1c5cef9

File tree

1 file changed

+39
-64
lines changed

1 file changed

+39
-64
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 39 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,13 @@ impl Res {
106106
Res::Primitive(_) => return Suggestion::Prefix("prim"),
107107
Res::Def(kind, _) => kind,
108108
};
109-
if kind == DefKind::Macro(MacroKind::Bang) {
110-
return Suggestion::Macro;
111-
} else if kind == DefKind::Fn || kind == DefKind::AssocFn {
112-
return Suggestion::Function;
113-
} else if kind == DefKind::Field {
114-
return Suggestion::RemoveDisambiguator;
115-
}
116109

117110
let prefix = match kind {
111+
DefKind::Fn | DefKind::AssocFn => return Suggestion::Function,
112+
DefKind::Field => return Suggestion::RemoveDisambiguator,
113+
DefKind::Macro(MacroKind::Bang) => return Suggestion::Macro,
114+
115+
DefKind::Macro(MacroKind::Derive) => "derive",
118116
DefKind::Struct => "struct",
119117
DefKind::Enum => "enum",
120118
DefKind::Trait => "trait",
@@ -124,7 +122,6 @@ impl Res {
124122
"const"
125123
}
126124
DefKind::Static(_) => "static",
127-
DefKind::Macro(MacroKind::Derive) => "derive",
128125
// Now handle things that don't have a specific disambiguator
129126
_ => match kind
130127
.ns()
@@ -281,20 +278,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
281278

282279
debug!("looking for enum variant {path_str}");
283280
let mut split = path_str.rsplitn(3, "::");
284-
let variant_field_name = split
285-
.next()
286-
.map(|f| Symbol::intern(f))
287-
.expect("fold_item should ensure link is non-empty");
288-
let variant_name =
289-
// we're not sure this is a variant at all, so use the full string
290-
// If there's no second component, the link looks like `[path]`.
291-
// So there's no partial res and we should say the whole link failed to resolve.
292-
split.next().map(|f| Symbol::intern(f)).ok_or_else(no_res)?;
293-
let path = split
294-
.next()
295-
// If there's no third component, we saw `[a::b]` before and it failed to resolve.
296-
// So there's no partial res.
297-
.ok_or_else(no_res)?;
281+
let variant_field_name = Symbol::intern(split.next().unwrap());
282+
// We're not sure this is a variant at all, so use the full string.
283+
// If there's no second component, the link looks like `[path]`.
284+
// So there's no partial res and we should say the whole link failed to resolve.
285+
let variant_name = Symbol::intern(split.next().ok_or_else(no_res)?);
286+
287+
// If there's no third component, we saw `[a::b]` before and it failed to resolve.
288+
// So there's no partial res.
289+
let path = split.next().ok_or_else(no_res)?;
298290
let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?;
299291

300292
match ty_res {
@@ -443,41 +435,29 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
443435
}
444436

445437
// Try looking for methods and associated items.
446-
let mut split = path_str.rsplitn(2, "::");
447-
// NB: `split`'s first element is always defined, even if the delimiter was not present.
448-
// NB: `item_str` could be empty when resolving in the root namespace (e.g. `::std`).
449-
let item_str = split.next().unwrap();
450-
let item_name = Symbol::intern(item_str);
451-
let path_root = split
452-
.next()
438+
// NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`).
439+
let (path_root, item_str) = path_str.rsplit_once("::").ok_or_else(|| {
453440
// If there's no `::`, it's not an associated item.
454441
// So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
455-
.ok_or_else(|| {
456-
debug!("found no `::`, assuming {item_name} was correctly not in scope");
457-
UnresolvedPath {
458-
item_id,
459-
module_id,
460-
partial_res: None,
461-
unresolved: item_str.into(),
462-
}
463-
})?;
442+
debug!("found no `::`, assuming {path_str} was correctly not in scope");
443+
UnresolvedPath { item_id, module_id, partial_res: None, unresolved: path_str.into() }
444+
})?;
445+
let item_name = Symbol::intern(item_str);
464446

465447
// FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
466448
// links to primitives when `#[rustc_doc_primitive]` is present. It should give an ambiguity
467449
// error instead and special case *only* modules with `#[rustc_doc_primitive]`, not all
468450
// primitives.
469-
match resolve_primitive(&path_root, TypeNS)
470-
.or_else(|| self.resolve_path(&path_root, TypeNS, item_id, module_id))
471-
.and_then(|ty_res| {
472-
let candidates = self
473-
.resolve_associated_item(ty_res, item_name, ns, module_id)
451+
match resolve_primitive(path_root, TypeNS)
452+
.or_else(|| self.resolve_path(path_root, TypeNS, item_id, module_id))
453+
.map(|ty_res| {
454+
self.resolve_associated_item(ty_res, item_name, ns, module_id)
474455
.into_iter()
475456
.map(|(res, def_id)| (res, Some(def_id)))
476-
.collect::<Vec<_>>();
477-
if !candidates.is_empty() { Some(candidates) } else { None }
457+
.collect::<Vec<_>>()
478458
}) {
479-
Some(r) => Ok(r),
480-
None => {
459+
Some(r) if !r.is_empty() => Ok(r),
460+
_ => {
481461
if ns == Namespace::ValueNS {
482462
self.variant_field(path_str, item_id, module_id)
483463
.map(|(res, def_id)| vec![(res, Some(def_id))])
@@ -1257,16 +1237,18 @@ impl LinkCollector<'_, '_> {
12571237
self.report_rawptr_assoc_feature_gate(diag.dox, &diag.link_range, diag.item);
12581238
return None;
12591239
} else {
1260-
candidates = vec![candidates[0]];
1240+
candidates = vec![*candidate];
12611241
}
12621242
}
12631243

12641244
// If there are multiple items with the same "kind" (for example, both "associated types")
12651245
// and after removing duplicated kinds, only one remains, the `ambiguity_error` function
12661246
// won't emit an error. So at this point, we can just take the first candidate as it was
12671247
// the first retrieved and use it to generate the link.
1268-
if candidates.len() > 1 && !ambiguity_error(self.cx, &diag, &key.path_str, &candidates) {
1269-
candidates = vec![candidates[0]];
1248+
if let [candidate, _candidate2, ..] = *candidates
1249+
&& !ambiguity_error(self.cx, &diag, &key.path_str, &candidates)
1250+
{
1251+
candidates = vec![candidate];
12701252
}
12711253

12721254
if let &[(res, def_id)] = candidates.as_slice() {
@@ -1316,12 +1298,11 @@ impl LinkCollector<'_, '_> {
13161298
let mut err = ResolutionFailure::NotResolved(err);
13171299
for other_ns in [TypeNS, ValueNS, MacroNS] {
13181300
if other_ns != expected_ns {
1319-
if let Ok(res) =
1320-
self.resolve(path_str, other_ns, item_id, module_id) &&
1321-
!res.is_empty()
1301+
if let Ok(&[res, ..]) =
1302+
self.resolve(path_str, other_ns, item_id, module_id).as_deref()
13221303
{
13231304
err = ResolutionFailure::WrongNamespace {
1324-
res: full_res(self.cx.tcx, res[0]),
1305+
res: full_res(self.cx.tcx, res),
13251306
expected_ns,
13261307
};
13271308
break;
@@ -1746,7 +1727,6 @@ fn report_diagnostic(
17461727
lint.note(format!(
17471728
"the link appears in this line:\n\n{line}\n\
17481729
{indicator: <before$}{indicator:^<found$}",
1749-
line = line,
17501730
indicator = "",
17511731
before = md_range.start - last_new_line_offset,
17521732
found = md_range.len(),
@@ -1807,18 +1787,13 @@ fn resolution_failure(
18071787

18081788
let item_id = *item_id;
18091789
let module_id = *module_id;
1810-
// FIXME(jynelson): this might conflict with my `Self` fix in #76467
1811-
// FIXME: maybe use itertools `collect_tuple` instead?
1812-
fn split(path: &str) -> Option<(&str, &str)> {
1813-
let mut splitter = path.rsplitn(2, "::");
1814-
splitter.next().and_then(|right| splitter.next().map(|left| (left, right)))
1815-
}
18161790

18171791
// Check if _any_ parent of the path gets resolved.
18181792
// If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
18191793
let mut name = path_str;
18201794
'outer: loop {
1821-
let Some((start, end)) = split(name) else {
1795+
// FIXME(jynelson): this might conflict with my `Self` fix in #76467
1796+
let Some((start, end)) = name.rsplit_once("::") else {
18221797
// avoid bug that marked [Quux::Z] as missing Z, not Quux
18231798
if partial_res.is_none() {
18241799
*unresolved = name.into();
@@ -1829,8 +1804,8 @@ fn resolution_failure(
18291804
for ns in [TypeNS, ValueNS, MacroNS] {
18301805
if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) {
18311806
debug!("found partial_res={v_res:?}");
1832-
if !v_res.is_empty() {
1833-
*partial_res = Some(full_res(tcx, v_res[0]));
1807+
if let Some(&res) = v_res.first() {
1808+
*partial_res = Some(full_res(tcx, res));
18341809
*unresolved = end.into();
18351810
break 'outer;
18361811
}

0 commit comments

Comments
 (0)