@@ -316,7 +316,8 @@ trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
316316fn item_module ( w : & mut Buffer , cx : & mut Context < ' _ > , item : & clean:: Item , items : & [ clean:: Item ] ) {
317317 write ! ( w, "{}" , document( cx, item, None , HeadingOffset :: H2 ) ) ;
318318
319- let mut indices = ( 0 ..items. len ( ) ) . filter ( |i| !items[ * i] . is_stripped ( ) ) . collect :: < Vec < usize > > ( ) ;
319+ let mut not_stripped_items =
320+ items. iter ( ) . filter ( |i| !i. is_stripped ( ) ) . enumerate ( ) . collect :: < Vec < _ > > ( ) ;
320321
321322 // the order of item types in the listing
322323 fn reorder ( ty : ItemType ) -> u8 {
@@ -338,37 +339,29 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
338339 }
339340 }
340341
341- fn cmp (
342- i1 : & clean:: Item ,
343- i2 : & clean:: Item ,
344- idx1 : usize ,
345- idx2 : usize ,
346- tcx : TyCtxt < ' _ > ,
347- ) -> Ordering {
348- let ty1 = i1. type_ ( ) ;
349- let ty2 = i2. type_ ( ) ;
350- if item_ty_to_section ( ty1) != item_ty_to_section ( ty2)
351- || ( ty1 != ty2 && ( ty1 == ItemType :: ExternCrate || ty2 == ItemType :: ExternCrate ) )
352- {
353- return ( reorder ( ty1) , idx1) . cmp ( & ( reorder ( ty2) , idx2) ) ;
354- }
355- let s1 = i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level ) ;
356- let s2 = i2. stability ( tcx) . as_ref ( ) . map ( |s| s. level ) ;
357- if let ( Some ( a) , Some ( b) ) = ( s1, s2) {
358- match ( a. is_stable ( ) , b. is_stable ( ) ) {
359- ( true , true ) | ( false , false ) => { }
360- ( false , true ) => return Ordering :: Greater ,
361- ( true , false ) => return Ordering :: Less ,
362- }
342+ fn cmp ( i1 : & clean:: Item , i2 : & clean:: Item , tcx : TyCtxt < ' _ > ) -> Ordering {
343+ let rty1 = reorder ( i1. type_ ( ) ) ;
344+ let rty2 = reorder ( i2. type_ ( ) ) ;
345+ if rty1 != rty2 {
346+ return rty1. cmp ( & rty2) ;
347+ }
348+ let is_stable1 = i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
349+ let is_stable2 = i2. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
350+ if is_stable1 != is_stable2 {
351+ // true is bigger than false in the standard bool ordering,
352+ // but we actually want stable items to come first
353+ return is_stable2. cmp ( & is_stable1) ;
363354 }
364355 let lhs = i1. name . unwrap_or ( kw:: Empty ) ;
365356 let rhs = i2. name . unwrap_or ( kw:: Empty ) ;
366357 compare_names ( lhs. as_str ( ) , rhs. as_str ( ) )
367358 }
368359
360+ let tcx = cx. tcx ( ) ;
361+
369362 match cx. shared . module_sorting {
370363 ModuleSorting :: Alphabetical => {
371- indices . sort_by ( |& i1 , & i2 | cmp ( & items [ i1 ] , & items [ i2 ] , i1 , i2 , cx . tcx ( ) ) ) ;
364+ not_stripped_items . sort_by ( |( _ , i1 ) , ( _ , i2 ) | cmp ( i1 , i2 , tcx) ) ;
372365 }
373366 ModuleSorting :: DeclarationOrder => { }
374367 }
@@ -391,24 +384,19 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
391384 // can be identical even if the elements are different (mostly in imports).
392385 // So in case this is an import, we keep everything by adding a "unique id"
393386 // (which is the position in the vector).
394- indices . dedup_by_key ( |i | {
387+ not_stripped_items . dedup_by_key ( |( idx , i ) | {
395388 (
396- items [ * i ] . item_id ,
397- if items [ * i ] . name . is_some ( ) { Some ( full_path ( cx, & items [ * i ] ) ) } else { None } ,
398- items [ * i ] . type_ ( ) ,
399- if items [ * i ] . is_import ( ) { * i } else { 0 } ,
389+ i . item_id ,
390+ if i . name . is_some ( ) { Some ( full_path ( cx, i ) ) } else { None } ,
391+ i . type_ ( ) ,
392+ if i . is_import ( ) { * idx } else { 0 } ,
400393 )
401394 } ) ;
402395
403- debug ! ( "{indices :?}" ) ;
396+ debug ! ( "{not_stripped_items :?}" ) ;
404397 let mut last_section = None ;
405398
406- for & idx in & indices {
407- let myitem = & items[ idx] ;
408- if myitem. is_stripped ( ) {
409- continue ;
410- }
411-
399+ for ( _, myitem) in & not_stripped_items {
412400 let my_section = item_ty_to_section ( myitem. type_ ( ) ) ;
413401 if Some ( my_section) != last_section {
414402 if last_section. is_some ( ) {
@@ -424,7 +412,6 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
424412 ) ;
425413 }
426414
427- let tcx = cx. tcx ( ) ;
428415 match * myitem. kind {
429416 clean:: ExternCrateItem { ref src } => {
430417 use crate :: html:: format:: anchor;
@@ -453,7 +440,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
453440 let stab_tags = if let Some ( import_def_id) = import. source . did {
454441 // Just need an item with the correct def_id and attrs
455442 let import_item =
456- clean:: Item { item_id : import_def_id. into ( ) , ..myitem. clone ( ) } ;
443+ clean:: Item { item_id : import_def_id. into ( ) , ..( * myitem) . clone ( ) } ;
457444
458445 let stab_tags = Some ( extra_info_tags ( & import_item, item, tcx) . to_string ( ) ) ;
459446 stab_tags
@@ -2010,40 +1997,102 @@ fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
20101997}
20111998
20121999/// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order).
2013- pub ( crate ) fn compare_names ( mut lhs : & str , mut rhs : & str ) -> Ordering {
2014- /// Takes a non-numeric and a numeric part from the given &str.
2015- fn take_parts < ' a > ( s : & mut & ' a str ) -> ( & ' a str , & ' a str ) {
2016- let i = s. find ( |c : char | c. is_ascii_digit ( ) ) ;
2017- let ( a, b) = s. split_at ( i. unwrap_or ( s. len ( ) ) ) ;
2018- let i = b. find ( |c : char | !c. is_ascii_digit ( ) ) ;
2019- let ( b, c) = b. split_at ( i. unwrap_or ( b. len ( ) ) ) ;
2020- * s = c;
2021- ( a, b)
2022- }
2023-
2024- while !lhs. is_empty ( ) || !rhs. is_empty ( ) {
2025- let ( la, lb) = take_parts ( & mut lhs) ;
2026- let ( ra, rb) = take_parts ( & mut rhs) ;
2027- // First process the non-numeric part.
2028- match la. cmp ( ra) {
2029- Ordering :: Equal => ( ) ,
2030- x => return x,
2031- }
2032- // Then process the numeric part, if both sides have one (and they fit in a u64).
2033- if let ( Ok ( ln) , Ok ( rn) ) = ( lb. parse :: < u64 > ( ) , rb. parse :: < u64 > ( ) ) {
2034- match ln. cmp ( & rn) {
2035- Ordering :: Equal => ( ) ,
2036- x => return x,
2000+ ///
2001+ /// This code is copied from [`rustfmt`], and should probably be released as a crate at some point.
2002+ ///
2003+ /// [`rustfmt`]:https://github.com/rust-lang/rustfmt/blob/rustfmt-2.0.0-rc.2/src/formatting/reorder.rs#L32
2004+ pub ( crate ) fn compare_names ( left : & str , right : & str ) -> Ordering {
2005+ let mut left = left. chars ( ) . peekable ( ) ;
2006+ let mut right = right. chars ( ) . peekable ( ) ;
2007+
2008+ loop {
2009+ // The strings are equal so far and not inside a number in both sides
2010+ let ( l, r) = match ( left. next ( ) , right. next ( ) ) {
2011+ // Is this the end of both strings?
2012+ ( None , None ) => return Ordering :: Equal ,
2013+ // If for one, the shorter one is considered smaller
2014+ ( None , Some ( _) ) => return Ordering :: Less ,
2015+ ( Some ( _) , None ) => return Ordering :: Greater ,
2016+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2017+ } ;
2018+ let next_ordering = match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2019+ // If neither is a digit, just compare them
2020+ ( None , None ) => Ord :: cmp ( & l, & r) ,
2021+ // The one with shorter non-digit run is smaller
2022+ // For `strverscmp` it's smaller iff next char in longer is greater than digits
2023+ ( None , Some ( _) ) => Ordering :: Greater ,
2024+ ( Some ( _) , None ) => Ordering :: Less ,
2025+ // If both start numbers, we have to compare the numbers
2026+ ( Some ( l) , Some ( r) ) => {
2027+ if l == 0 || r == 0 {
2028+ // Fraction mode: compare as if there was leading `0.`
2029+ let ordering = Ord :: cmp ( & l, & r) ;
2030+ if ordering != Ordering :: Equal {
2031+ return ordering;
2032+ }
2033+ loop {
2034+ // Get next pair
2035+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2036+ // Is this the end of both strings?
2037+ ( None , None ) => return Ordering :: Equal ,
2038+ // If for one, the shorter one is considered smaller
2039+ ( None , Some ( _) ) => return Ordering :: Less ,
2040+ ( Some ( _) , None ) => return Ordering :: Greater ,
2041+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2042+ } ;
2043+ // Are they digits?
2044+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2045+ // If out of digits, use the stored ordering due to equal length
2046+ ( None , None ) => break Ordering :: Equal ,
2047+ // If one is shorter, it's smaller
2048+ ( None , Some ( _) ) => return Ordering :: Less ,
2049+ ( Some ( _) , None ) => return Ordering :: Greater ,
2050+ // If both are digits, consume them and take into account
2051+ ( Some ( l) , Some ( r) ) => {
2052+ left. next ( ) ;
2053+ right. next ( ) ;
2054+ let ordering = Ord :: cmp ( & l, & r) ;
2055+ if ordering != Ordering :: Equal {
2056+ return ordering;
2057+ }
2058+ }
2059+ }
2060+ }
2061+ } else {
2062+ // Integer mode
2063+ let mut same_length_ordering = Ord :: cmp ( & l, & r) ;
2064+ loop {
2065+ // Get next pair
2066+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2067+ // Is this the end of both strings?
2068+ ( None , None ) => return same_length_ordering,
2069+ // If for one, the shorter one is considered smaller
2070+ ( None , Some ( _) ) => return Ordering :: Less ,
2071+ ( Some ( _) , None ) => return Ordering :: Greater ,
2072+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2073+ } ;
2074+ // Are they digits?
2075+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2076+ // If out of digits, use the stored ordering due to equal length
2077+ ( None , None ) => break same_length_ordering,
2078+ // If one is shorter, it's smaller
2079+ ( None , Some ( _) ) => return Ordering :: Less ,
2080+ ( Some ( _) , None ) => return Ordering :: Greater ,
2081+ // If both are digits, consume them and take into account
2082+ ( Some ( l) , Some ( r) ) => {
2083+ left. next ( ) ;
2084+ right. next ( ) ;
2085+ same_length_ordering = same_length_ordering. then ( Ord :: cmp ( & l, & r) ) ;
2086+ }
2087+ }
2088+ }
2089+ }
20372090 }
2038- }
2039- // Then process the numeric part again, but this time as strings.
2040- match lb. cmp ( rb) {
2041- Ordering :: Equal => ( ) ,
2042- x => return x,
2091+ } ;
2092+ if next_ordering != Ordering :: Equal {
2093+ return next_ordering;
20432094 }
20442095 }
2045-
2046- Ordering :: Equal
20472096}
20482097
20492098pub ( super ) fn full_path ( cx : & Context < ' _ > , item : & clean:: Item ) -> String {
0 commit comments