@@ -5,7 +5,7 @@ use std::iter;
55use askama:: Template ;
66use rustc_abi:: VariantIdx ;
77use rustc_ast:: join_path_syms;
8- use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
8+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap , FxIndexSet } ;
99use rustc_hir as hir;
1010use rustc_hir:: def:: CtorKind ;
1111use rustc_hir:: def_id:: DefId ;
@@ -307,8 +307,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
307307 fmt:: from_fn ( |w| {
308308 write ! ( w, "{}" , document( cx, item, None , HeadingOffset :: H2 ) ) ?;
309309
310- let mut not_stripped_items =
311- items. iter ( ) . filter ( |i| !i. is_stripped ( ) ) . enumerate ( ) . collect :: < Vec < _ > > ( ) ;
310+ let mut not_stripped_items: FxIndexMap < ItemType , Vec < ( usize , & clean:: Item ) > > =
311+ FxIndexMap :: default ( ) ;
312+
313+ for ( index, item) in items. iter ( ) . filter ( |i| !i. is_stripped ( ) ) . enumerate ( ) {
314+ not_stripped_items. entry ( item. type_ ( ) ) . or_default ( ) . push ( ( index, item) ) ;
315+ }
312316
313317 // the order of item types in the listing
314318 fn reorder ( ty : ItemType ) -> u8 {
@@ -331,11 +335,6 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
331335 }
332336
333337 fn cmp ( i1 : & clean:: Item , i2 : & clean:: Item , tcx : TyCtxt < ' _ > ) -> Ordering {
334- let rty1 = reorder ( i1. type_ ( ) ) ;
335- let rty2 = reorder ( i2. type_ ( ) ) ;
336- if rty1 != rty2 {
337- return rty1. cmp ( & rty2) ;
338- }
339338 let is_stable1 =
340339 i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
341340 let is_stable2 =
@@ -357,7 +356,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
357356
358357 match cx. shared . module_sorting {
359358 ModuleSorting :: Alphabetical => {
360- not_stripped_items. sort_by ( |( _, i1) , ( _, i2) | cmp ( i1, i2, tcx) ) ;
359+ for items in not_stripped_items. values_mut ( ) {
360+ items. sort_by ( |( _, i1) , ( _, i2) | cmp ( i1, i2, tcx) ) ;
361+ }
361362 }
362363 ModuleSorting :: DeclarationOrder => { }
363364 }
@@ -380,155 +381,152 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
380381 // can be identical even if the elements are different (mostly in imports).
381382 // So in case this is an import, we keep everything by adding a "unique id"
382383 // (which is the position in the vector).
383- not_stripped_items. dedup_by_key ( |( idx, i) | {
384- (
385- i. item_id ,
386- if i. name . is_some ( ) { Some ( full_path ( cx, i) ) } else { None } ,
387- i. type_ ( ) ,
388- if i. is_import ( ) { * idx } else { 0 } ,
389- )
390- } ) ;
384+ for items in not_stripped_items. values_mut ( ) {
385+ items. dedup_by_key ( |( idx, i) | {
386+ (
387+ i. item_id ,
388+ if i. name . is_some ( ) { Some ( full_path ( cx, i) ) } else { None } ,
389+ i. type_ ( ) ,
390+ if i. is_import ( ) { * idx } else { 0 } ,
391+ )
392+ } ) ;
393+ }
391394
392395 debug ! ( "{not_stripped_items:?}" ) ;
393- let mut last_section = None ;
394396
395- for ( _, myitem) in & not_stripped_items {
396- let my_section = item_ty_to_section ( myitem. type_ ( ) ) ;
397- if Some ( my_section) != last_section {
398- if last_section. is_some ( ) {
399- w. write_str ( ITEM_TABLE_CLOSE ) ?;
400- }
401- last_section = Some ( my_section) ;
402- let section_id = my_section. id ( ) ;
403- let tag =
404- if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN } ;
405- write ! (
406- w,
407- "{}" ,
408- write_section_heading( my_section. name( ) , & cx. derive_id( section_id) , None , tag)
409- ) ?;
410- }
411-
412- match myitem. kind {
413- clean:: ExternCrateItem { ref src } => {
414- use crate :: html:: format:: print_anchor;
397+ let mut types = not_stripped_items. keys ( ) . copied ( ) . collect :: < Vec < _ > > ( ) ;
398+ types. sort_unstable_by ( |a, b| reorder ( * a) . cmp ( & reorder ( * b) ) ) ;
415399
416- match * src {
417- Some ( src) => {
418- write ! (
419- w,
420- "<dt><code>{}extern crate {} as {};" ,
421- visibility_print_with_space( myitem, cx) ,
422- print_anchor( myitem. item_id. expect_def_id( ) , src, cx) ,
423- EscapeBodyTextWithWbr ( myitem. name. unwrap( ) . as_str( ) )
424- ) ?;
425- }
426- None => {
427- write ! (
428- w,
429- "<dt><code>{}extern crate {};" ,
430- visibility_print_with_space( myitem, cx) ,
431- print_anchor(
432- myitem. item_id. expect_def_id( ) ,
433- myitem. name. unwrap( ) ,
434- cx
435- )
436- ) ?;
437- }
438- }
439- w. write_str ( "</code></dt>" ) ?;
440- }
400+ for type_ in types {
401+ let my_section = item_ty_to_section ( type_) ;
402+ let tag = if my_section == super :: ItemSection :: Reexports {
403+ REEXPORTS_TABLE_OPEN
404+ } else {
405+ ITEM_TABLE_OPEN
406+ } ;
407+ write ! (
408+ w,
409+ "{}" ,
410+ write_section_heading( my_section. name( ) , & cx. derive_id( my_section. id( ) ) , None , tag)
411+ ) ?;
441412
442- clean :: ImportItem ( ref import ) => {
443- let stab_tags = import . source . did . map_or_else ( String :: new , |import_def_id| {
444- print_extra_info_tags ( tcx , myitem , item , Some ( import_def_id ) ) . to_string ( )
445- } ) ;
413+ for ( _ , myitem ) in & not_stripped_items [ & type_ ] {
414+ match myitem . kind {
415+ clean :: ExternCrateItem { ref src } => {
416+ use crate :: html :: format :: print_anchor ;
446417
447- let id = match import. kind {
448- clean:: ImportKind :: Simple ( s) => {
449- format ! ( " id=\" {}\" " , cx. derive_id( format!( "reexport.{s}" ) ) )
418+ match * src {
419+ Some ( src) => {
420+ write ! (
421+ w,
422+ "<dt><code>{}extern crate {} as {};" ,
423+ visibility_print_with_space( myitem, cx) ,
424+ print_anchor( myitem. item_id. expect_def_id( ) , src, cx) ,
425+ EscapeBodyTextWithWbr ( myitem. name. unwrap( ) . as_str( ) )
426+ ) ?;
427+ }
428+ None => {
429+ write ! (
430+ w,
431+ "<dt><code>{}extern crate {};" ,
432+ visibility_print_with_space( myitem, cx) ,
433+ print_anchor(
434+ myitem. item_id. expect_def_id( ) ,
435+ myitem. name. unwrap( ) ,
436+ cx
437+ )
438+ ) ?;
439+ }
450440 }
451- clean:: ImportKind :: Glob => String :: new ( ) ,
452- } ;
453- write ! (
454- w,
455- "<dt{id}>\
456- <code>"
457- ) ?;
458- render_attributes_in_code ( w, myitem, "" , cx) ;
459- write ! (
460- w,
461- "{vis}{imp}</code>{stab_tags}\
462- </dt>",
463- vis = visibility_print_with_space( myitem, cx) ,
464- imp = import. print( cx)
465- ) ?;
466- }
467-
468- _ => {
469- if myitem. name . is_none ( ) {
470- continue ;
471441 }
472-
473- let unsafety_flag = match myitem. kind {
474- clean:: FunctionItem ( _) | clean:: ForeignFunctionItem ( ..)
475- if myitem. fn_header ( tcx) . unwrap ( ) . safety
476- == hir:: HeaderSafety :: Normal ( hir:: Safety :: Unsafe ) =>
477- {
478- "<sup title=\" unsafe function\" >⚠</sup>"
479- }
480- clean:: ForeignStaticItem ( _, hir:: Safety :: Unsafe ) => {
481- "<sup title=\" unsafe static\" >⚠</sup>"
482- }
483- _ => "" ,
484- } ;
485-
486- let visibility_and_hidden = match myitem. visibility ( tcx) {
487- Some ( ty:: Visibility :: Restricted ( _) ) => {
488- if myitem. is_doc_hidden ( ) {
489- // Don't separate with a space when there are two of them
490- "<span title=\" Restricted Visibility\" > 🔒</span><span title=\" Hidden item\" >👻</span> "
491- } else {
492- "<span title=\" Restricted Visibility\" > 🔒</span> "
442+ clean:: ImportItem ( ref import) => {
443+ let stab_tags =
444+ import. source . did . map_or_else ( String :: new, |import_def_id| {
445+ print_extra_info_tags ( tcx, myitem, item, Some ( import_def_id) )
446+ . to_string ( )
447+ } ) ;
448+ let id = match import. kind {
449+ clean:: ImportKind :: Simple ( s) => {
450+ format ! ( " id=\" {}\" " , cx. derive_id( format!( "reexport.{s}" ) ) )
493451 }
452+ clean:: ImportKind :: Glob => String :: new ( ) ,
453+ } ;
454+ write ! (
455+ w,
456+ "<dt{id}>\
457+ <code>"
458+ ) ?;
459+ render_attributes_in_code ( w, myitem, "" , cx) ;
460+ write ! (
461+ w,
462+ "{vis}{imp}</code>{stab_tags}\
463+ </dt>",
464+ vis = visibility_print_with_space( myitem, cx) ,
465+ imp = import. print( cx)
466+ ) ?;
467+ }
468+ _ => {
469+ if myitem. name . is_none ( ) {
470+ continue ;
494471 }
495- _ if myitem. is_doc_hidden ( ) => {
496- "<span title=\" Hidden item\" > 👻</span> "
497- }
498- _ => "" ,
499- } ;
500472
501- let docs =
502- MarkdownSummaryLine ( & myitem. doc_value ( ) , & myitem. links ( cx) ) . into_string ( ) ;
503- let ( docs_before, docs_after) =
504- if docs. is_empty ( ) { ( "" , "" ) } else { ( "<dd>" , "</dd>" ) } ;
505- write ! (
506- w,
507- "<dt>\
508- <a class=\" {class}\" href=\" {href}\" title=\" {title1} {title2}\" >\
509- {name}\
510- </a>\
511- {visibility_and_hidden}\
512- {unsafety_flag}\
513- {stab_tags}\
514- </dt>\
515- {docs_before}{docs}{docs_after}",
516- name = EscapeBodyTextWithWbr ( myitem. name. unwrap( ) . as_str( ) ) ,
517- visibility_and_hidden = visibility_and_hidden,
518- stab_tags = print_extra_info_tags( tcx, myitem, item, None ) ,
519- class = myitem. type_( ) ,
520- unsafety_flag = unsafety_flag,
521- href = print_item_path( myitem. type_( ) , myitem. name. unwrap( ) . as_str( ) ) ,
522- title1 = myitem. type_( ) ,
523- title2 = full_path( cx, myitem) ,
524- ) ?;
473+ let unsafety_flag = match myitem. kind {
474+ clean:: FunctionItem ( _) | clean:: ForeignFunctionItem ( ..)
475+ if myitem. fn_header ( tcx) . unwrap ( ) . safety
476+ == hir:: HeaderSafety :: Normal ( hir:: Safety :: Unsafe ) =>
477+ {
478+ "<sup title=\" unsafe function\" >⚠</sup>"
479+ }
480+ clean:: ForeignStaticItem ( _, hir:: Safety :: Unsafe ) => {
481+ "<sup title=\" unsafe static\" >⚠</sup>"
482+ }
483+ _ => "" ,
484+ } ;
485+ let visibility_and_hidden = match myitem. visibility ( tcx) {
486+ Some ( ty:: Visibility :: Restricted ( _) ) => {
487+ if myitem. is_doc_hidden ( ) {
488+ // Don't separate with a space when there are two of them
489+ "<span title=\" Restricted Visibility\" > 🔒</span><span title=\" Hidden item\" >👻</span> "
490+ } else {
491+ "<span title=\" Restricted Visibility\" > 🔒</span> "
492+ }
493+ }
494+ _ if myitem. is_doc_hidden ( ) => {
495+ "<span title=\" Hidden item\" > 👻</span> "
496+ }
497+ _ => "" ,
498+ } ;
499+
500+ let docs = MarkdownSummaryLine ( & myitem. doc_value ( ) , & myitem. links ( cx) )
501+ . into_string ( ) ;
502+ let ( docs_before, docs_after) =
503+ if docs. is_empty ( ) { ( "" , "" ) } else { ( "<dd>" , "</dd>" ) } ;
504+ write ! (
505+ w,
506+ "<dt>\
507+ <a class=\" {class}\" href=\" {href}\" title=\" {title1} {title2}\" >\
508+ {name}\
509+ </a>\
510+ {visibility_and_hidden}\
511+ {unsafety_flag}\
512+ {stab_tags}\
513+ </dt>\
514+ {docs_before}{docs}{docs_after}",
515+ name = EscapeBodyTextWithWbr ( myitem. name. unwrap( ) . as_str( ) ) ,
516+ visibility_and_hidden = visibility_and_hidden,
517+ stab_tags = print_extra_info_tags( tcx, myitem, item, None ) ,
518+ class = type_,
519+ unsafety_flag = unsafety_flag,
520+ href = print_item_path( type_, myitem. name. unwrap( ) . as_str( ) ) ,
521+ title1 = myitem. type_( ) ,
522+ title2 = full_path( cx, myitem) ,
523+ ) ?;
524+ }
525525 }
526526 }
527- }
528-
529- if last_section. is_some ( ) {
530527 w. write_str ( ITEM_TABLE_CLOSE ) ?;
531528 }
529+
532530 Ok ( ( ) )
533531 } )
534532}
0 commit comments