@@ -368,54 +368,30 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
368368 }
369369
370370 /// 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.
374371 fn resolve_primitive_associated_item (
375372 & self ,
376373 prim_ty : PrimitiveType ,
377374 ns : Namespace ,
378- module_id : DefId ,
379375 item_name : Symbol ,
380- ) -> Result < ( Res , Option < String > ) , ErrorKind < ' path > > {
376+ ) -> Option < ( Res , String ) > {
381377 let tcx = self . cx . tcx ;
382378
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+ } )
419395 }
420396
421397 /// Resolves a string as a macro.
@@ -533,7 +509,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
533509
534510 self . resolve_path ( & path_root, TypeNS , module_id)
535511 . 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)
537526 } )
538527 . unwrap_or_else ( || {
539528 if ns == Namespace :: ValueNS {
@@ -549,21 +538,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
549538 } )
550539 }
551540
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
552545 fn resolve_associated_item (
553546 & mut self ,
554547 root_res : Res ,
555548 item_name : Symbol ,
556549 ns : Namespace ,
557550 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 ) > ) > {
561552 let tcx = self . cx . tcx ;
562553
563554 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 ) ) ,
567558 Res :: Def (
568559 DefKind :: Struct
569560 | DefKind :: Union
@@ -606,17 +597,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
606597 ty:: AssocKind :: Const => "associatedconstant" ,
607598 ty:: AssocKind :: Type => "associatedtype" ,
608599 } ;
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+ ) ) ;
620608 }
621609
622610 if ns != Namespace :: ValueNS {
@@ -635,22 +623,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
635623 } else {
636624 def. non_enum_variant ( ) . fields . iter ( ) . find ( |item| item. ident . name == item_name)
637625 } ?;
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+ ) )
654635 }
655636 Res :: Def ( DefKind :: Trait , did) => tcx
656637 . associated_items ( did)
@@ -668,14 +649,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
668649 }
669650 } ;
670651
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 )
679654 } ) ,
680655 _ => None ,
681656 }
0 commit comments