rustdoc: sort stable items first

This commit is contained in:
binarycat 2025-11-29 12:04:31 -06:00
parent a234ae6b65
commit dca86a9521
11 changed files with 58 additions and 4 deletions

View file

@ -431,6 +431,10 @@ impl Item {
self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect())
}
pub(crate) fn is_unstable(&self) -> bool {
self.stability.is_some_and(|x| x.is_unstable())
}
pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
}

View file

@ -594,6 +594,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
);
let aliases = item.attrs.get_doc_aliases();
let is_deprecated = item.is_deprecated(tcx);
let is_unstable = item.is_unstable();
let index_item = IndexItem {
ty: item.type_(),
defid: Some(defid),
@ -609,6 +610,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
search_type,
aliases,
is_deprecated,
is_unstable,
};
cache.search_index.push(index_item);

View file

@ -142,6 +142,7 @@ pub(crate) struct IndexItem {
pub(crate) search_type: Option<IndexItemFunctionType>,
pub(crate) aliases: Box<[Symbol]>,
pub(crate) is_deprecated: bool,
pub(crate) is_unstable: bool,
}
/// A type used for the search index.

View file

@ -616,6 +616,7 @@ impl SerializedSearchIndex {
parent,
trait_parent,
deprecated,
unstable,
associated_item_disambiguator,
}| EntryData {
krate: *map.get(krate).unwrap(),
@ -626,6 +627,7 @@ impl SerializedSearchIndex {
parent: parent.and_then(|path_id| map.get(&path_id).copied()),
trait_parent: trait_parent.and_then(|path_id| map.get(&path_id).copied()),
deprecated: *deprecated,
unstable: *unstable,
associated_item_disambiguator: associated_item_disambiguator.clone(),
},
),
@ -896,6 +898,7 @@ struct EntryData {
parent: Option<usize>,
trait_parent: Option<usize>,
deprecated: bool,
unstable: bool,
associated_item_disambiguator: Option<String>,
}
@ -912,6 +915,7 @@ impl Serialize for EntryData {
seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?;
seq.serialize_element(&self.trait_parent.map(|id| id + 1).unwrap_or(0))?;
seq.serialize_element(&if self.deprecated { 1 } else { 0 })?;
seq.serialize_element(&if self.unstable { 1 } else { 0 })?;
if let Some(disambig) = &self.associated_item_disambiguator {
seq.serialize_element(&disambig)?;
}
@ -946,6 +950,7 @@ impl<'de> Deserialize<'de> for EntryData {
v.next_element()?.ok_or_else(|| A::Error::missing_field("trait_parent"))?;
let deprecated: u32 = v.next_element()?.unwrap_or(0);
let unstable: u32 = v.next_element()?.unwrap_or(0);
let associated_item_disambiguator: Option<String> = v.next_element()?;
Ok(EntryData {
krate,
@ -956,6 +961,7 @@ impl<'de> Deserialize<'de> for EntryData {
parent: Option::<i32>::from(parent).map(|path| path as usize),
trait_parent: Option::<i32>::from(trait_parent).map(|path| path as usize),
deprecated: deprecated != 0,
unstable: unstable != 0,
associated_item_disambiguator,
})
}
@ -1283,6 +1289,7 @@ pub(crate) fn build_index(
),
aliases: item.attrs.get_doc_aliases(),
is_deprecated: item.is_deprecated(tcx),
is_unstable: item.is_unstable(),
});
}
}
@ -1382,6 +1389,7 @@ pub(crate) fn build_index(
parent: None,
trait_parent: None,
deprecated: false,
unstable: false,
associated_item_disambiguator: None,
}),
crate_doc,
@ -1520,6 +1528,7 @@ pub(crate) fn build_index(
module_path,
exact_module_path,
deprecated: item.is_deprecated,
unstable: item.is_unstable,
associated_item_disambiguator: if let Some(impl_id) = item.impl_id
&& let Some(parent_idx) = item.parent_idx
&& associated_item_duplicates

View file

@ -243,6 +243,7 @@ declare namespace rustdoc {
parent: number?,
traitParent: number?,
deprecated: boolean,
unstable: boolean,
associatedItemDisambiguator: string?,
}
@ -292,6 +293,7 @@ declare namespace rustdoc {
path: PathData?,
functionData: FunctionData?,
deprecated: boolean,
unstable: boolean,
parent: RowParent,
traitParent: RowParent,
}

View file

@ -1633,6 +1633,7 @@ class DocSearch {
* parent,
* trait_parent,
* deprecated,
* unstable,
* associated_item_disambiguator
* @type {rustdoc.ArrayWithOptionals<[
* number,
@ -1642,6 +1643,7 @@ class DocSearch {
* number,
* number,
* number,
* number,
* ], [string]>}
*/
const raw = JSON.parse(encoded);
@ -1653,7 +1655,8 @@ class DocSearch {
parent: raw[4] === 0 ? null : raw[4] - 1,
traitParent: raw[5] === 0 ? null : raw[5] - 1,
deprecated: raw[6] === 1 ? true : false,
associatedItemDisambiguator: raw.length === 7 ? null : raw[7],
unstable: raw[7] === 1 ? true : false,
associatedItemDisambiguator: raw.length === 8 ? null : raw[8],
};
}
@ -1946,6 +1949,7 @@ class DocSearch {
path,
functionData,
deprecated: entry ? entry.deprecated : false,
unstable: entry ? entry.unstable : false,
parent,
traitParent,
};
@ -2858,6 +2862,13 @@ class DocSearch {
return a - b;
}
// sort unstable items later
a = Number(aai.unstable);
b = Number(bbi.unstable);
if (a !== b) {
return a - b;
}
// sort by crate (current crate comes first)
a = Number(aai.crate !== preferredCrate);
b = Number(bbi.crate !== preferredCrate);

View file

@ -3,9 +3,9 @@ const EXPECTED = [
{
'query': 'generic:T -> generic:U',
'others': [
{ 'path': 'core::mem', 'name': 'transmute' },
{ 'path': 'core::intrinsics::simd', 'name': 'simd_as' },
{ 'path': 'core::intrinsics::simd', 'name': 'simd_cast' },
{ 'path': 'core::mem', 'name': 'transmute' },
],
},
];

View file

@ -6,9 +6,9 @@ const EXPECTED = [
// should-fail tag and the search query below:
'query': 'generic:T -> generic:T',
'others': [
{ 'path': 'std::mem', 'name': 'transmute' },
{ 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
{ 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
{ 'path': 'std::mem', 'name': 'transmute' },
],
},
];

View file

@ -5,9 +5,9 @@ const EXPECTED = [
// should-fail tag and the search query below:
'query': 'generic:T -> generic:U',
'others': [
{ 'path': 'std::mem', 'name': 'transmute' },
{ 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
{ 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
{ 'path': 'std::mem', 'name': 'transmute' },
],
},
];

View file

@ -0,0 +1,9 @@
const EXPECTED = [
{
'query': 'foo',
'others': [
{"path": "sort_stability::old", "name": "foo"},
{"path": "sort_stability::new", "name": "foo"},
],
},
];

View file

@ -0,0 +1,16 @@
#![feature(staged_api)]
#![stable(feature = "foo_lib", since = "1.0.0")]
#[stable(feature = "old_foo", since = "1.0.1")]
pub mod old {
/// Old, stable foo
#[stable(feature = "old_foo", since = "1.0.1")]
pub fn foo() {}
}
#[unstable(feature = "new_foo", issue = "none")]
pub mod new {
/// New, unstable foo
#[unstable(feature = "new_foo", issue = "none")]
pub fn foo() {}
}