Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a324fc1

Browse files
committed
Only check for conflicting anchors in one place
This coalesces the checks into one place.
1 parent 3b50a4e commit a324fc1

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,31 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
513513
path_str: &'path str,
514514
ns: Namespace,
515515
module_id: DefId,
516-
extra_fragment: &Option<UrlFragment>,
516+
user_fragment: &Option<UrlFragment>,
517+
) -> Result<(Res, Option<UrlFragment>), ErrorKind<'path>> {
518+
let (res, rustdoc_fragment) = self.resolve_inner(path_str, ns, module_id)?;
519+
let chosen_fragment = match (user_fragment, rustdoc_fragment) {
520+
(Some(_), Some(r_frag)) => {
521+
let diag_res = match r_frag {
522+
UrlFragment::Def(_, did) => Res::Def(self.cx.tcx.def_kind(did), did),
523+
// FIXME: eliminate this branch somehow
524+
UrlFragment::UserWritten(_) => unreachable!(),
525+
};
526+
let failure = AnchorFailure::RustdocAnchorConflict(diag_res);
527+
return Err(ErrorKind::AnchorFailure(failure));
528+
}
529+
(Some(u_frag), None) => Some(u_frag.clone()),
530+
(None, Some(r_frag)) => Some(r_frag),
531+
(None, None) => None,
532+
};
533+
Ok((res, chosen_fragment))
534+
}
535+
536+
fn resolve_inner<'path>(
537+
&mut self,
538+
path_str: &'path str,
539+
ns: Namespace,
540+
module_id: DefId,
517541
) -> Result<(Res, Option<UrlFragment>), ErrorKind<'path>> {
518542
if let Some(res) = self.resolve_path(path_str, ns, module_id) {
519543
match res {
@@ -522,17 +546,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
522546
Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
523547
Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
524548
Res::Def(DefKind::Variant, _) => {
525-
if extra_fragment.is_some() {
526-
// NOTE: `res` can never be a primitive since this match arm means
527-
// `tcx.def_kind(res) == DefKind::Variant`.
528-
return Err(ErrorKind::AnchorFailure(
529-
AnchorFailure::RustdocAnchorConflict(res),
530-
));
531-
}
532549
return handle_variant(self.cx, res);
533550
}
534551
// Not a trait item; just return what we found.
535-
_ => return Ok((res, extra_fragment.clone())),
552+
_ => return Ok((res, None)),
536553
}
537554
}
538555

@@ -565,21 +582,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
565582
.and_then(|ty_res| {
566583
let (res, fragment, side_channel) =
567584
self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
568-
let result = if extra_fragment.is_some() {
569-
// NOTE: can never be a primitive since `side_channel.is_none()` only when `res`
570-
// is a trait (and the side channel DefId is always an associated item).
571-
let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r));
572-
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res)))
573-
} else {
574-
// HACK(jynelson): `clean` expects the type, not the associated item
575-
// but the disambiguator logic expects the associated item.
576-
// Store the kind in a side channel so that only the disambiguator logic looks at it.
577-
if let Some((kind, id)) = side_channel {
578-
self.kind_side_channel.set(Some((kind, id)));
579-
}
580-
Ok((res, Some(fragment)))
581-
};
582-
Some(result)
585+
586+
// HACK(jynelson): `clean` expects the type, not the associated item
587+
// but the disambiguator logic expects the associated item.
588+
// Store the kind in a side channel so that only the disambiguator logic looks at it.
589+
if let Some((kind, id)) = side_channel {
590+
self.kind_side_channel.set(Some((kind, id)));
591+
}
592+
Some(Ok((res, Some(fragment))))
583593
})
584594
.unwrap_or_else(|| {
585595
if ns == Namespace::ValueNS {

0 commit comments

Comments
 (0)