Skip to content

Commit e3fdafc

Browse files
Fix Ord violations in rustdoc items sorting
1 parent 2ccafed commit e3fdafc

File tree

2 files changed

+40
-43
lines changed

2 files changed

+40
-43
lines changed

src/librustdoc/html/render/print_item.rs

+39-42
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
316316
fn 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,30 @@ 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 {
342+
fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
348343
let ty1 = i1.type_();
349344
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,
345+
if ty1 != ty2 {
346+
return reorder(ty1).cmp(&reorder(ty2));
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+
if !is_stable1 {
352+
return Ordering::Greater;
362353
}
354+
return Ordering::Less;
363355
}
364356
let lhs = i1.name.unwrap_or(kw::Empty);
365357
let rhs = i2.name.unwrap_or(kw::Empty);
366358
compare_names(lhs.as_str(), rhs.as_str())
367359
}
368360

361+
let tcx = cx.tcx();
362+
369363
match cx.shared.module_sorting {
370364
ModuleSorting::Alphabetical => {
371-
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2, cx.tcx()));
365+
not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
372366
}
373367
ModuleSorting::DeclarationOrder => {}
374368
}
@@ -391,24 +385,19 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
391385
// can be identical even if the elements are different (mostly in imports).
392386
// So in case this is an import, we keep everything by adding a "unique id"
393387
// (which is the position in the vector).
394-
indices.dedup_by_key(|i| {
388+
not_stripped_items.dedup_by_key(|(idx, i)| {
395389
(
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 },
390+
i.item_id,
391+
if i.name.is_some() { Some(full_path(cx, i)) } else { None },
392+
i.type_(),
393+
if i.is_import() { *idx } else { 0 },
400394
)
401395
});
402396

403-
debug!("{indices:?}");
397+
debug!("{not_stripped_items:?}");
404398
let mut last_section = None;
405399

406-
for &idx in &indices {
407-
let myitem = &items[idx];
408-
if myitem.is_stripped() {
409-
continue;
410-
}
411-
400+
for (_, myitem) in &not_stripped_items {
412401
let my_section = item_ty_to_section(myitem.type_());
413402
if Some(my_section) != last_section {
414403
if last_section.is_some() {
@@ -424,7 +413,6 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
424413
);
425414
}
426415

427-
let tcx = cx.tcx();
428416
match *myitem.kind {
429417
clean::ExternCrateItem { ref src } => {
430418
use crate::html::format::anchor;
@@ -453,7 +441,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
453441
let stab_tags = if let Some(import_def_id) = import.source.did {
454442
// Just need an item with the correct def_id and attrs
455443
let import_item =
456-
clean::Item { item_id: import_def_id.into(), ..myitem.clone() };
444+
clean::Item { item_id: import_def_id.into(), ..(*myitem).clone() };
457445

458446
let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string());
459447
stab_tags
@@ -2026,19 +2014,28 @@ pub(crate) fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering {
20262014
let (ra, rb) = take_parts(&mut rhs);
20272015
// First process the non-numeric part.
20282016
match la.cmp(ra) {
2029-
Ordering::Equal => (),
2017+
Ordering::Equal => {}
20302018
x => return x,
20312019
}
2020+
match (lb.is_empty(), rb.is_empty()) {
2021+
(true, false) => return Ordering::Less,
2022+
(false, true) => return Ordering::Greater,
2023+
(true, true) => continue,
2024+
(false, false) => {}
2025+
}
20322026
// 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 => (),
2027+
match (lb.parse::<u64>(), rb.parse::<u64>()) {
2028+
(Err(_), Err(_)) => return Ordering::Equal,
2029+
(Ok(_), Err(_)) => return Ordering::Less,
2030+
(Err(_), Ok(_)) => return Ordering::Greater,
2031+
(Ok(nb1), Ok(nb2)) => match nb1.cmp(&nb2) {
2032+
Ordering::Equal => {}
20362033
x => return x,
2037-
}
2034+
},
20382035
}
2039-
// Then process the numeric part again, but this time as strings.
2036+
// If both numbers are equal, then we compare the strings.
20402037
match lb.cmp(rb) {
2041-
Ordering::Equal => (),
2038+
Ordering::Equal => {}
20422039
x => return x,
20432040
}
20442041
}

src/librustdoc/html/render/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn test_compare_names() {
99
("hello", "world"),
1010
("", "world"),
1111
("123", "hello"),
12-
("123", ""),
12+
// ("123", ""),
1313
("123test", "123"),
1414
("hello", ""),
1515
("hello", "hello"),

0 commit comments

Comments
 (0)