@@ -368,54 +368,28 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
368
368
}
369
369
370
370
/// Given a primitive type, try to resolve an associated item.
371
- ///
372
- /// HACK(jynelson): `item_str` is passed in instead of derived from `item_name` so the
373
- /// lifetimes on `&'path` will work.
374
371
fn resolve_primitive_associated_item (
375
372
& self ,
376
373
prim_ty : PrimitiveType ,
377
374
ns : Namespace ,
378
- module_id : DefId ,
379
375
item_name : Symbol ,
380
- ) -> Result < ( Res , Option < String > ) , ErrorKind < ' path > > {
376
+ ) -> Option < ( Res , String , Option < ( DefKind , DefId ) > ) > {
381
377
let tcx = self . cx . tcx ;
382
378
383
- prim_ty
384
- . impls ( tcx)
385
- . into_iter ( )
386
- . find_map ( |& impl_| {
387
- tcx. associated_items ( impl_)
388
- . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, impl_)
389
- . map ( |item| {
390
- let kind = item. kind ;
391
- self . kind_side_channel . set ( Some ( ( kind. as_def_kind ( ) , item. def_id ) ) ) ;
392
- match kind {
393
- ty:: AssocKind :: Fn => "method" ,
394
- ty:: AssocKind :: Const => "associatedconstant" ,
395
- ty:: AssocKind :: Type => "associatedtype" ,
396
- }
397
- } )
398
- . map ( |out| {
399
- (
400
- Res :: Primitive ( prim_ty) ,
401
- Some ( format ! ( "{}#{}.{}" , prim_ty. as_str( ) , out, item_name) ) ,
402
- )
403
- } )
404
- } )
405
- . ok_or_else ( || {
406
- debug ! (
407
- "returning primitive error for {}::{} in {} namespace" ,
408
- prim_ty. as_str( ) ,
409
- item_name,
410
- ns. descr( )
411
- ) ;
412
- ResolutionFailure :: NotResolved {
413
- module_id,
414
- partial_res : Some ( Res :: Primitive ( prim_ty) ) ,
415
- unresolved : item_name. to_string ( ) . into ( ) ,
416
- }
417
- . into ( )
418
- } )
379
+ prim_ty. impls ( tcx) . into_iter ( ) . find_map ( |& impl_| {
380
+ tcx. associated_items ( impl_)
381
+ . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, impl_)
382
+ . map ( |item| {
383
+ let kind = item. kind ;
384
+ let out = match kind {
385
+ ty:: AssocKind :: Fn => "method" ,
386
+ ty:: AssocKind :: Const => "associatedconstant" ,
387
+ ty:: AssocKind :: Type => "associatedtype" ,
388
+ } ;
389
+ let fragment = format ! ( "{}#{}.{}" , prim_ty. as_str( ) , out, item_name) ;
390
+ ( Res :: Primitive ( prim_ty) , fragment, Some ( ( kind. as_def_kind ( ) , item. def_id ) ) )
391
+ } )
392
+ } )
419
393
}
420
394
421
395
/// Resolves a string as a macro.
@@ -538,7 +512,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
538
512
resolve_primitive ( & path_root, TypeNS )
539
513
. or_else ( || self . resolve_path ( & path_root, TypeNS , module_id) )
540
514
. and_then ( |ty_res| {
541
- self . resolve_associated_item ( ty_res, item_name, ns, module_id, extra_fragment)
515
+ let ( res, fragment, side_channel) =
516
+ self . resolve_associated_item ( ty_res, item_name, ns, module_id) ?;
517
+ let result = if extra_fragment. is_some ( ) {
518
+ let diag_res = side_channel. map_or ( res, |( k, r) | Res :: Def ( k, r) ) ;
519
+ Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict ( diag_res) ) )
520
+ } else {
521
+ // HACK(jynelson): `clean` expects the type, not the associated item
522
+ // but the disambiguator logic expects the associated item.
523
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
524
+ if let Some ( ( kind, id) ) = side_channel {
525
+ self . kind_side_channel . set ( Some ( ( kind, id) ) ) ;
526
+ }
527
+ Ok ( ( res, Some ( fragment) ) )
528
+ } ;
529
+ Some ( result)
542
530
} )
543
531
. unwrap_or_else ( || {
544
532
if ns == Namespace :: ValueNS {
@@ -554,21 +542,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
554
542
} )
555
543
}
556
544
545
+ /// Returns:
546
+ /// - None if no associated item was found
547
+ /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
548
+ /// - Some((_, _, None)) otherwise
557
549
fn resolve_associated_item (
558
550
& mut self ,
559
551
root_res : Res ,
560
552
item_name : Symbol ,
561
553
ns : Namespace ,
562
554
module_id : DefId ,
563
- extra_fragment : & Option < String > ,
564
- // lol this is so bad
565
- ) -> Option < Result < ( Res , Option < String > ) , ErrorKind < ' static > > > {
555
+ ) -> Option < ( Res , String , Option < ( DefKind , DefId ) > ) > {
566
556
let tcx = self . cx . tcx ;
567
557
568
558
match root_res {
569
- Res :: Primitive ( prim) => {
570
- Some ( self . resolve_primitive_associated_item ( prim, ns, module_id, item_name) )
571
- }
559
+ Res :: Primitive ( prim) => self . resolve_primitive_associated_item ( prim, ns, item_name) ,
572
560
Res :: Def (
573
561
DefKind :: Struct
574
562
| DefKind :: Union
@@ -611,17 +599,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
611
599
ty:: AssocKind :: Const => "associatedconstant" ,
612
600
ty:: AssocKind :: Type => "associatedtype" ,
613
601
} ;
614
- return Some ( if extra_fragment. is_some ( ) {
615
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict (
616
- root_res,
617
- ) ) )
618
- } else {
619
- // HACK(jynelson): `clean` expects the type, not the associated item
620
- // but the disambiguator logic expects the associated item.
621
- // Store the kind in a side channel so that only the disambiguator logic looks at it.
622
- self . kind_side_channel . set ( Some ( ( kind. as_def_kind ( ) , id) ) ) ;
623
- Ok ( ( root_res, Some ( format ! ( "{}.{}" , out, item_name) ) ) )
624
- } ) ;
602
+ // HACK(jynelson): `clean` expects the type, not the associated item
603
+ // but the disambiguator logic expects the associated item.
604
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
605
+ return Some ( (
606
+ root_res,
607
+ format ! ( "{}.{}" , out, item_name) ,
608
+ Some ( ( kind. as_def_kind ( ) , id) ) ,
609
+ ) ) ;
625
610
}
626
611
627
612
if ns != Namespace :: ValueNS {
@@ -640,22 +625,16 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
640
625
} else {
641
626
def. non_enum_variant ( ) . fields . iter ( ) . find ( |item| item. ident . name == item_name)
642
627
} ?;
643
- Some ( if extra_fragment. is_some ( ) {
644
- let res = Res :: Def (
645
- if def. is_enum ( ) { DefKind :: Variant } else { DefKind :: Field } ,
646
- field. did ,
647
- ) ;
648
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict ( res) ) )
649
- } else {
650
- Ok ( (
651
- root_res,
652
- Some ( format ! (
653
- "{}.{}" ,
654
- if def. is_enum( ) { "variant" } else { "structfield" } ,
655
- field. ident
656
- ) ) ,
657
- ) )
658
- } )
628
+ let kind = if def. is_enum ( ) { DefKind :: Variant } else { DefKind :: Field } ;
629
+ Some ( (
630
+ root_res,
631
+ format ! (
632
+ "{}.{}" ,
633
+ if def. is_enum( ) { "variant" } else { "structfield" } ,
634
+ field. ident
635
+ ) ,
636
+ Some ( ( kind, field. did ) ) ,
637
+ ) )
659
638
}
660
639
Res :: Def ( DefKind :: Trait , did) => tcx
661
640
. associated_items ( did)
@@ -673,14 +652,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
673
652
}
674
653
} ;
675
654
676
- if extra_fragment. is_some ( ) {
677
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict (
678
- root_res,
679
- ) ) )
680
- } else {
681
- let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
682
- Ok ( ( res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
683
- }
655
+ let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
656
+ ( res, format ! ( "{}.{}" , kind, item_name) , None )
684
657
} ) ,
685
658
_ => None ,
686
659
}
0 commit comments