@@ -513,7 +513,31 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
513
513
path_str : & ' path str ,
514
514
ns : Namespace ,
515
515
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 ,
517
541
) -> Result < ( Res , Option < UrlFragment > ) , ErrorKind < ' path > > {
518
542
if let Some ( res) = self . resolve_path ( path_str, ns, module_id) {
519
543
match res {
@@ -522,17 +546,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
522
546
Res :: Def ( DefKind :: AssocFn | DefKind :: AssocConst , _) => assert_eq ! ( ns, ValueNS ) ,
523
547
Res :: Def ( DefKind :: AssocTy , _) => assert_eq ! ( ns, TypeNS ) ,
524
548
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
- }
532
549
return handle_variant ( self . cx , res) ;
533
550
}
534
551
// Not a trait item; just return what we found.
535
- _ => return Ok ( ( res, extra_fragment . clone ( ) ) ) ,
552
+ _ => return Ok ( ( res, None ) ) ,
536
553
}
537
554
}
538
555
@@ -565,21 +582,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
565
582
. and_then ( |ty_res| {
566
583
let ( res, fragment, side_channel) =
567
584
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) ) ) )
583
593
} )
584
594
. unwrap_or_else ( || {
585
595
if ns == Namespace :: ValueNS {
0 commit comments