@@ -433,19 +433,97 @@ pub(crate) fn merge_attrs(
433433 }
434434}
435435
436+ /// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl` defined in the current crate.
437+ pub ( crate ) fn build_local_impl (
438+ cx : & mut DocContext < ' _ > ,
439+ did : DefId ,
440+ attrs : Option < ( & [ hir:: Attribute ] , Option < LocalDefId > ) > ,
441+ ret : & mut Vec < clean:: Item > ,
442+ ) {
443+ if !cx. inlined . insert ( did. into ( ) ) {
444+ return ;
445+ }
446+ debug_assert ! ( did. is_local( ) , "build_local_impl called on external impl" ) ;
447+ let tcx = cx. tcx ;
448+ let _prof_timer = tcx. sess . prof . generic_activity ( "build_local_impl" ) ;
449+
450+ let associated_trait = tcx. impl_trait_ref ( did) . map ( ty:: EarlyBinder :: skip_binder) ;
451+
452+ let impl_item = match did. as_local ( ) {
453+ Some ( did) => match & tcx. hir_expect_item ( did) . kind {
454+ hir:: ItemKind :: Impl ( impl_) => impl_,
455+ _ => panic ! ( "`DefID` passed to `build_impl` is not an `impl" ) ,
456+ } ,
457+ None => unreachable ! ( "build_local_impl called on external impl" ) ,
458+ } ;
459+
460+ let for_ = clean_ty ( impl_item. self_ty , cx) ;
461+
462+ let document_hidden = cx. render_options . document_hidden ;
463+ let ( trait_items, generics) = (
464+ impl_item
465+ . items
466+ . iter ( )
467+ . map ( |& item| tcx. hir_impl_item ( item) )
468+ . filter ( |item| {
469+ // Filter out impl items whose corresponding trait item has `doc(hidden)`
470+ // not to document such impl items.
471+ // For inherent impls, we don't do any filtering, because that's already done in strip_hidden.rs.
472+
473+ // When `--document-hidden-items` is passed, we don't
474+ // do any filtering, too.
475+ if document_hidden {
476+ return true ;
477+ }
478+ if let Some ( associated_trait) = associated_trait {
479+ let assoc_tag = match item. kind {
480+ hir:: ImplItemKind :: Const ( ..) => ty:: AssocTag :: Const ,
481+ hir:: ImplItemKind :: Fn ( ..) => ty:: AssocTag :: Fn ,
482+ hir:: ImplItemKind :: Type ( ..) => ty:: AssocTag :: Type ,
483+ } ;
484+ let trait_item = tcx
485+ . associated_items ( associated_trait. def_id )
486+ . find_by_ident_and_kind ( tcx, item. ident , assoc_tag, associated_trait. def_id )
487+ . unwrap ( ) ; // SAFETY: For all impl items there exists trait item that has the same name.
488+ !tcx. is_doc_hidden ( trait_item. def_id )
489+ } else {
490+ true
491+ }
492+ } )
493+ . map ( |item| clean_impl_item ( item, cx) )
494+ . collect :: < Vec < _ > > ( ) ,
495+ clean_generics ( impl_item. generics , cx) ,
496+ ) ;
497+ build_impl_finalize ( cx, did, attrs, ret, associated_trait, for_, trait_items, generics)
498+ }
499+
436500/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`.
437501pub ( crate ) fn build_impl (
438502 cx : & mut DocContext < ' _ > ,
439503 did : DefId ,
440504 attrs : Option < ( & [ hir:: Attribute ] , Option < LocalDefId > ) > ,
441505 ret : & mut Vec < clean:: Item > ,
506+ ) {
507+ if did. is_local ( ) {
508+ build_local_impl ( cx, did, attrs, ret) ;
509+ } else {
510+ build_external_impl ( cx, did, attrs, ret) ;
511+ }
512+ }
513+
514+ /// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl` defined in an external crate.
515+ pub ( crate ) fn build_external_impl (
516+ cx : & mut DocContext < ' _ > ,
517+ did : DefId ,
518+ attrs : Option < ( & [ hir:: Attribute ] , Option < LocalDefId > ) > ,
519+ ret : & mut Vec < clean:: Item > ,
442520) {
443521 if !cx. inlined . insert ( did. into ( ) ) {
444522 return ;
445523 }
446524
447525 let tcx = cx. tcx ;
448- let _prof_timer = tcx. sess . prof . generic_activity ( "build_impl " ) ;
526+ let _prof_timer = tcx. sess . prof . generic_activity ( "build_external_impl " ) ;
449527
450528 let associated_trait = tcx. impl_trait_ref ( did) . map ( ty:: EarlyBinder :: skip_binder) ;
451529
@@ -462,30 +540,18 @@ pub(crate) fn build_impl(
462540
463541 // Only inline impl if the implemented trait is
464542 // reachable in rustdoc generated documentation
465- if !did. is_local ( )
466- && let Some ( traitref) = associated_trait
543+ if let Some ( traitref) = associated_trait
467544 && !is_directly_public ( cx, traitref. def_id )
468545 {
469546 return ;
470547 }
471548
472- let impl_item = match did. as_local ( ) {
473- Some ( did) => match & tcx. hir_expect_item ( did) . kind {
474- hir:: ItemKind :: Impl ( impl_) => Some ( impl_) ,
475- _ => panic ! ( "`DefID` passed to `build_impl` is not an `impl" ) ,
476- } ,
477- None => None ,
478- } ;
479-
480- let for_ = match & impl_item {
481- Some ( impl_) => clean_ty ( impl_. self_ty , cx) ,
482- None => clean_middle_ty (
483- ty:: Binder :: dummy ( tcx. type_of ( did) . instantiate_identity ( ) ) ,
484- cx,
485- Some ( did) ,
486- None ,
487- ) ,
488- } ;
549+ let for_ = clean_middle_ty (
550+ ty:: Binder :: dummy ( tcx. type_of ( did) . instantiate_identity ( ) ) ,
551+ cx,
552+ Some ( did) ,
553+ None ,
554+ ) ;
489555
490556 // Only inline impl if the implementing type is
491557 // reachable in rustdoc generated documentation
@@ -496,82 +562,57 @@ pub(crate) fn build_impl(
496562 return ;
497563 }
498564
565+ debug_assert ! ( !did. is_local( ) , "build_external_impl called on local impl" ) ;
566+
567+ let document_hidden = cx. render_options . document_hidden ;
568+ let ( trait_items, generics) = (
569+ tcx. associated_items ( did)
570+ . in_definition_order ( )
571+ . filter ( |item| !item. is_impl_trait_in_trait ( ) )
572+ . filter ( |item| {
573+ // If this is a trait impl, filter out associated items whose corresponding item
574+ // in the associated trait is marked `doc(hidden)`.
575+ // If this is an inherent impl, filter out private associated items.
576+ if let Some ( associated_trait) = associated_trait {
577+ let trait_item = tcx
578+ . associated_items ( associated_trait. def_id )
579+ . find_by_ident_and_kind (
580+ tcx,
581+ item. ident ( tcx) ,
582+ item. as_tag ( ) ,
583+ associated_trait. def_id ,
584+ )
585+ . unwrap ( ) ; // corresponding associated item has to exist
586+ document_hidden || !tcx. is_doc_hidden ( trait_item. def_id )
587+ } else {
588+ item. visibility ( tcx) . is_public ( )
589+ }
590+ } )
591+ . map ( |item| clean_middle_assoc_item ( item, cx) )
592+ . collect :: < Vec < _ > > ( ) ,
593+ clean:: enter_impl_trait ( cx, |cx| clean_ty_generics ( cx, did) ) ,
594+ ) ;
595+ build_impl_finalize ( cx, did, attrs, ret, associated_trait, for_, trait_items, generics)
596+ }
597+
598+ fn build_impl_finalize < ' tcx > (
599+ cx : & mut DocContext < ' tcx > ,
600+ did : DefId ,
601+ attrs : Option < ( & [ rustc_hir:: Attribute ] , Option < LocalDefId > ) > ,
602+ ret : & mut Vec < Item > ,
603+ associated_trait : Option < ty:: TraitRef < ' tcx > > ,
604+ for_ : Type ,
605+ trait_items : Vec < Item > ,
606+ generics : clean:: Generics ,
607+ ) {
608+ let tcx = cx. tcx ;
499609 let document_hidden = cx. render_options . document_hidden ;
500- let ( trait_items, generics) = match impl_item {
501- Some ( impl_) => (
502- impl_
503- . items
504- . iter ( )
505- . map ( |& item| tcx. hir_impl_item ( item) )
506- . filter ( |item| {
507- // Filter out impl items whose corresponding trait item has `doc(hidden)`
508- // not to document such impl items.
509- // For inherent impls, we don't do any filtering, because that's already done in strip_hidden.rs.
510-
511- // When `--document-hidden-items` is passed, we don't
512- // do any filtering, too.
513- if document_hidden {
514- return true ;
515- }
516- if let Some ( associated_trait) = associated_trait {
517- let assoc_tag = match item. kind {
518- hir:: ImplItemKind :: Const ( ..) => ty:: AssocTag :: Const ,
519- hir:: ImplItemKind :: Fn ( ..) => ty:: AssocTag :: Fn ,
520- hir:: ImplItemKind :: Type ( ..) => ty:: AssocTag :: Type ,
521- } ;
522- let trait_item = tcx
523- . associated_items ( associated_trait. def_id )
524- . find_by_ident_and_kind (
525- tcx,
526- item. ident ,
527- assoc_tag,
528- associated_trait. def_id ,
529- )
530- . unwrap ( ) ; // SAFETY: For all impl items there exists trait item that has the same name.
531- !tcx. is_doc_hidden ( trait_item. def_id )
532- } else {
533- true
534- }
535- } )
536- . map ( |item| clean_impl_item ( item, cx) )
537- . collect :: < Vec < _ > > ( ) ,
538- clean_generics ( impl_. generics , cx) ,
539- ) ,
540- None => (
541- tcx. associated_items ( did)
542- . in_definition_order ( )
543- . filter ( |item| !item. is_impl_trait_in_trait ( ) )
544- . filter ( |item| {
545- // If this is a trait impl, filter out associated items whose corresponding item
546- // in the associated trait is marked `doc(hidden)`.
547- // If this is an inherent impl, filter out private associated items.
548- if let Some ( associated_trait) = associated_trait {
549- let trait_item = tcx
550- . associated_items ( associated_trait. def_id )
551- . find_by_ident_and_kind (
552- tcx,
553- item. ident ( tcx) ,
554- item. as_tag ( ) ,
555- associated_trait. def_id ,
556- )
557- . unwrap ( ) ; // corresponding associated item has to exist
558- document_hidden || !tcx. is_doc_hidden ( trait_item. def_id )
559- } else {
560- item. visibility ( tcx) . is_public ( )
561- }
562- } )
563- . map ( |item| clean_middle_assoc_item ( item, cx) )
564- . collect :: < Vec < _ > > ( ) ,
565- clean:: enter_impl_trait ( cx, |cx| clean_ty_generics ( cx, did) ) ,
566- ) ,
567- } ;
568610 let polarity = tcx. impl_polarity ( did) ;
569611 let trait_ = associated_trait
570612 . map ( |t| clean_trait_ref_with_constraints ( cx, ty:: Binder :: dummy ( t) , ThinVec :: new ( ) ) ) ;
571613 if trait_. as_ref ( ) . map ( |t| t. def_id ( ) ) == tcx. lang_items ( ) . deref_trait ( ) {
572614 super :: build_deref_target_impls ( cx, & trait_items, ret) ;
573615 }
574-
575616 if !document_hidden {
576617 // Return if the trait itself or any types of the generic parameters are doc(hidden).
577618 let mut stack: Vec < & Type > = vec ! [ & for_] ;
@@ -597,16 +638,13 @@ pub(crate) fn build_impl(
597638 }
598639 }
599640 }
600-
601641 if let Some ( did) = trait_. as_ref ( ) . map ( |t| t. def_id ( ) ) {
602642 cx. with_param_env ( did, |cx| {
603643 record_extern_trait ( cx, did) ;
604644 } ) ;
605645 }
606-
607646 let ( merged_attrs, cfg) = merge_attrs ( cx, load_attrs ( cx, did) , attrs) ;
608647 trace ! ( "merged_attrs={merged_attrs:?}" ) ;
609-
610648 trace ! (
611649 "build_impl: impl {:?} for {:?}" ,
612650 trait_. as_ref( ) . map( |t| t. def_id( ) ) ,
@@ -620,7 +658,7 @@ pub(crate) fn build_impl(
620658 generics,
621659 trait_,
622660 for_,
623- items : trait_items,
661+ items : trait_items. to_vec ( ) ,
624662 polarity,
625663 kind : if utils:: has_doc_flag ( tcx, did, sym:: fake_variadic) {
626664 ImplKind :: FakeVariadic
0 commit comments