@@ -368,54 +368,30 @@ 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 ) > {
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
+ self . kind_side_channel . set ( Some ( ( kind. as_def_kind ( ) , item. def_id ) ) ) ;
385
+ match kind {
386
+ ty:: AssocKind :: Fn => "method" ,
387
+ ty:: AssocKind :: Const => "associatedconstant" ,
388
+ ty:: AssocKind :: Type => "associatedtype" ,
389
+ }
390
+ } )
391
+ . map ( |out| {
392
+ ( Res :: Primitive ( prim_ty) , format ! ( "{}#{}.{}" , prim_ty. as_str( ) , out, item_name) )
393
+ } )
394
+ } )
419
395
}
420
396
421
397
/// Resolves a string as a macro.
@@ -533,7 +509,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
533
509
534
510
self . resolve_path ( & path_root, TypeNS , module_id)
535
511
. and_then ( |ty_res| {
536
- self . resolve_associated_item ( ty_res, item_name, ns, module_id, extra_fragment)
512
+ let ( res, fragment, side_channel) =
513
+ self . resolve_associated_item ( ty_res, item_name, ns, module_id) ?;
514
+ let result = if extra_fragment. is_some ( ) {
515
+ Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict ( res) ) )
516
+ } else {
517
+ // HACK(jynelson): `clean` expects the type, not the associated item
518
+ // but the disambiguator logic expects the associated item.
519
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
520
+ if let Some ( ( kind, id) ) = side_channel {
521
+ self . kind_side_channel . set ( Some ( ( kind, id) ) ) ;
522
+ }
523
+ Ok ( ( res, Some ( fragment) ) )
524
+ } ;
525
+ Some ( result)
537
526
} )
538
527
. unwrap_or_else ( || {
539
528
if ns == Namespace :: ValueNS {
@@ -549,21 +538,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
549
538
} )
550
539
}
551
540
541
+ /// Returns:
542
+ /// - None if no associated item was found
543
+ /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
544
+ /// - Some((_, _, None)) otherwise
552
545
fn resolve_associated_item (
553
546
& mut self ,
554
547
root_res : Res ,
555
548
item_name : Symbol ,
556
549
ns : Namespace ,
557
550
module_id : DefId ,
558
- extra_fragment : & Option < String > ,
559
- // lol this is so bad
560
- ) -> Option < Result < ( Res , Option < String > ) , ErrorKind < ' static > > > {
551
+ ) -> Option < ( Res , String , Option < ( DefKind , DefId ) > ) > {
561
552
let tcx = self . cx . tcx ;
562
553
563
554
match root_res {
564
- Res :: Primitive ( prim) => {
565
- Some ( self . resolve_primitive_associated_item ( prim, ns, module_id , item_name) )
566
- }
555
+ Res :: Primitive ( prim) => self
556
+ . resolve_primitive_associated_item ( prim, ns, item_name)
557
+ . map ( | ( x , y ) | ( x , y , None ) ) ,
567
558
Res :: Def (
568
559
DefKind :: Struct
569
560
| DefKind :: Union
@@ -606,17 +597,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
606
597
ty:: AssocKind :: Const => "associatedconstant" ,
607
598
ty:: AssocKind :: Type => "associatedtype" ,
608
599
} ;
609
- return Some ( if extra_fragment. is_some ( ) {
610
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict (
611
- root_res,
612
- ) ) )
613
- } else {
614
- // HACK(jynelson): `clean` expects the type, not the associated item
615
- // but the disambiguator logic expects the associated item.
616
- // Store the kind in a side channel so that only the disambiguator logic looks at it.
617
- self . kind_side_channel . set ( Some ( ( kind. as_def_kind ( ) , id) ) ) ;
618
- Ok ( ( root_res, Some ( format ! ( "{}.{}" , out, item_name) ) ) )
619
- } ) ;
600
+ // HACK(jynelson): `clean` expects the type, not the associated item
601
+ // but the disambiguator logic expects the associated item.
602
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
603
+ return Some ( (
604
+ root_res,
605
+ format ! ( "{}.{}" , out, item_name) ,
606
+ Some ( ( kind. as_def_kind ( ) , id) ) ,
607
+ ) ) ;
620
608
}
621
609
622
610
if ns != Namespace :: ValueNS {
@@ -635,22 +623,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
635
623
} else {
636
624
def. non_enum_variant ( ) . fields . iter ( ) . find ( |item| item. ident . name == item_name)
637
625
} ?;
638
- Some ( if extra_fragment. is_some ( ) {
639
- let res = Res :: Def (
640
- if def. is_enum ( ) { DefKind :: Variant } else { DefKind :: Field } ,
641
- field. did ,
642
- ) ;
643
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict ( res) ) )
644
- } else {
645
- Ok ( (
646
- root_res,
647
- Some ( format ! (
648
- "{}.{}" ,
649
- if def. is_enum( ) { "variant" } else { "structfield" } ,
650
- field. ident
651
- ) ) ,
652
- ) )
653
- } )
626
+ Some ( (
627
+ root_res,
628
+ format ! (
629
+ "{}.{}" ,
630
+ if def. is_enum( ) { "variant" } else { "structfield" } ,
631
+ field. ident
632
+ ) ,
633
+ None ,
634
+ ) )
654
635
}
655
636
Res :: Def ( DefKind :: Trait , did) => tcx
656
637
. associated_items ( did)
@@ -668,14 +649,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
668
649
}
669
650
} ;
670
651
671
- if extra_fragment. is_some ( ) {
672
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict (
673
- root_res,
674
- ) ) )
675
- } else {
676
- let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
677
- Ok ( ( res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
678
- }
652
+ let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
653
+ ( res, format ! ( "{}.{}" , kind, item_name) , None )
679
654
} ) ,
680
655
_ => None ,
681
656
}
0 commit comments