@@ -316,7 +316,8 @@ trait ItemTemplate<'a, 'cx: 'a>: rinja::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 {
@@ -341,34 +342,30 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
341342 fn cmp (
342343 i1 : & clean:: Item ,
343344 i2 : & clean:: Item ,
344- idx1 : usize ,
345- idx2 : usize ,
346345 tcx : TyCtxt < ' _ > ,
347346 ) -> 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- }
347+ let rty1 = reorder ( i1. type_ ( ) ) ;
348+ let rty2 = reorder ( i2. type_ ( ) ) ;
349+ if rty1 != rty2 {
350+ return rty1. cmp ( & rty2) ;
351+ }
352+ let is_stable1 = i1. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
353+ let is_stable2 = i2. stability ( tcx) . as_ref ( ) . map ( |s| s. level . is_stable ( ) ) . unwrap_or ( true ) ;
354+ if is_stable1 != is_stable2 {
355+ // true is bigger than false in the standard bool ordering,
356+ // but we actually want stable items to come first
357+ return is_stable2. cmp ( & is_stable1) ;
363358 }
364359 let lhs = i1. name . unwrap_or ( kw:: Empty ) ;
365360 let rhs = i2. name . unwrap_or ( kw:: Empty ) ;
366361 compare_names ( lhs. as_str ( ) , rhs. as_str ( ) )
367362 }
368363
364+ let tcx = cx. tcx ( ) ;
365+
369366 match cx. shared . module_sorting {
370367 ModuleSorting :: Alphabetical => {
371- indices . sort_by ( |& i1 , & i2 | cmp ( & items [ i1 ] , & items [ i2 ] , i1 , i2 , cx . tcx ( ) ) ) ;
368+ not_stripped_items . sort_by ( |( _ , i1 ) , ( _ , i2 ) | cmp ( i1 , i2 , tcx) ) ;
372369 }
373370 ModuleSorting :: DeclarationOrder => { }
374371 }
@@ -391,24 +388,19 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
391388 // can be identical even if the elements are different (mostly in imports).
392389 // So in case this is an import, we keep everything by adding a "unique id"
393390 // (which is the position in the vector).
394- indices . dedup_by_key ( |i | {
391+ not_stripped_items . dedup_by_key ( |( idx , i ) | {
395392 (
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 } ,
393+ i . item_id ,
394+ if i . name . is_some ( ) { Some ( full_path ( cx, i ) ) } else { None } ,
395+ i . type_ ( ) ,
396+ if i . is_import ( ) { * idx } else { 0 } ,
400397 )
401398 } ) ;
402399
403- debug ! ( "{indices :?}" ) ;
400+ debug ! ( "{not_stripped_items :?}" ) ;
404401 let mut last_section = None ;
405402
406- for & idx in & indices {
407- let myitem = & items[ idx] ;
408- if myitem. is_stripped ( ) {
409- continue ;
410- }
411-
403+ for ( _, myitem) in & not_stripped_items {
412404 let my_section = item_ty_to_section ( myitem. type_ ( ) ) ;
413405 if Some ( my_section) != last_section {
414406 if last_section. is_some ( ) {
@@ -424,7 +416,6 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
424416 ) ;
425417 }
426418
427- let tcx = cx. tcx ( ) ;
428419 match * myitem. kind {
429420 clean:: ExternCrateItem { ref src } => {
430421 use crate :: html:: format:: anchor;
@@ -453,7 +444,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
453444 let stab_tags = if let Some ( import_def_id) = import. source . did {
454445 // Just need an item with the correct def_id and attrs
455446 let import_item =
456- clean:: Item { item_id : import_def_id. into ( ) , ..myitem. clone ( ) } ;
447+ clean:: Item { item_id : import_def_id. into ( ) , ..( * myitem) . clone ( ) } ;
457448
458449 let stab_tags = Some ( extra_info_tags ( & import_item, item, tcx) . to_string ( ) ) ;
459450 stab_tags
@@ -2010,40 +2001,102 @@ fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
20102001}
20112002
20122003/// 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,
2004+ ///
2005+ /// This code is copied from [`rustfmt`], and should probably be released as a crate at some point.
2006+ ///
2007+ /// [`rustfmt`]:https://github.com/rust-lang/rustfmt/blob/rustfmt-2.0.0-rc.2/src/formatting/reorder.rs#L32
2008+ pub ( crate ) fn compare_names ( left : & str , right : & str ) -> Ordering {
2009+ let mut left = left. chars ( ) . peekable ( ) ;
2010+ let mut right = right. chars ( ) . peekable ( ) ;
2011+
2012+ loop {
2013+ // The strings are equal so far and not inside a number in both sides
2014+ let ( l, r) = match ( left. next ( ) , right. next ( ) ) {
2015+ // Is this the end of both strings?
2016+ ( None , None ) => return Ordering :: Equal ,
2017+ // If for one, the shorter one is considered smaller
2018+ ( None , Some ( _) ) => return Ordering :: Less ,
2019+ ( Some ( _) , None ) => return Ordering :: Greater ,
2020+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2021+ } ;
2022+ let next_ordering = match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2023+ // If neither is a digit, just compare them
2024+ ( None , None ) => Ord :: cmp ( & l, & r) ,
2025+ // The one with shorter non-digit run is smaller
2026+ // For `strverscmp` it's smaller iff next char in longer is greater than digits
2027+ ( None , Some ( _) ) => Ordering :: Greater ,
2028+ ( Some ( _) , None ) => Ordering :: Less ,
2029+ // If both start numbers, we have to compare the numbers
2030+ ( Some ( l) , Some ( r) ) => {
2031+ if l == 0 || r == 0 {
2032+ // Fraction mode: compare as if there was leading `0.`
2033+ let ordering = Ord :: cmp ( & l, & r) ;
2034+ if ordering != Ordering :: Equal {
2035+ return ordering;
2036+ }
2037+ loop {
2038+ // Get next pair
2039+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2040+ // Is this the end of both strings?
2041+ ( None , None ) => return Ordering :: Equal ,
2042+ // If for one, the shorter one is considered smaller
2043+ ( None , Some ( _) ) => return Ordering :: Less ,
2044+ ( Some ( _) , None ) => return Ordering :: Greater ,
2045+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2046+ } ;
2047+ // Are they digits?
2048+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2049+ // If out of digits, use the stored ordering due to equal length
2050+ ( None , None ) => break Ordering :: Equal ,
2051+ // If one is shorter, it's smaller
2052+ ( None , Some ( _) ) => return Ordering :: Less ,
2053+ ( Some ( _) , None ) => return Ordering :: Greater ,
2054+ // If both are digits, consume them and take into account
2055+ ( Some ( l) , Some ( r) ) => {
2056+ left. next ( ) ;
2057+ right. next ( ) ;
2058+ let ordering = Ord :: cmp ( & l, & r) ;
2059+ if ordering != Ordering :: Equal {
2060+ return ordering;
2061+ }
2062+ }
2063+ }
2064+ }
2065+ } else {
2066+ // Integer mode
2067+ let mut same_length_ordering = Ord :: cmp ( & l, & r) ;
2068+ loop {
2069+ // Get next pair
2070+ let ( l, r) = match ( left. peek ( ) , right. peek ( ) ) {
2071+ // Is this the end of both strings?
2072+ ( None , None ) => return same_length_ordering,
2073+ // If for one, the shorter one is considered smaller
2074+ ( None , Some ( _) ) => return Ordering :: Less ,
2075+ ( Some ( _) , None ) => return Ordering :: Greater ,
2076+ ( Some ( l) , Some ( r) ) => ( l, r) ,
2077+ } ;
2078+ // Are they digits?
2079+ match ( l. to_digit ( 10 ) , r. to_digit ( 10 ) ) {
2080+ // If out of digits, use the stored ordering due to equal length
2081+ ( None , None ) => break same_length_ordering,
2082+ // If one is shorter, it's smaller
2083+ ( None , Some ( _) ) => return Ordering :: Less ,
2084+ ( Some ( _) , None ) => return Ordering :: Greater ,
2085+ // If both are digits, consume them and take into account
2086+ ( Some ( l) , Some ( r) ) => {
2087+ left. next ( ) ;
2088+ right. next ( ) ;
2089+ same_length_ordering = same_length_ordering. then ( Ord :: cmp ( & l, & r) ) ;
2090+ }
2091+ }
2092+ }
2093+ }
20372094 }
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,
2095+ } ;
2096+ if next_ordering != Ordering :: Equal {
2097+ return next_ordering;
20432098 }
20442099 }
2045-
2046- Ordering :: Equal
20472100}
20482101
20492102pub ( super ) fn full_path ( cx : & Context < ' _ > , item : & clean:: Item ) -> String {
0 commit comments