diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-08-09 13:58:42 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-09 13:58:42 +1000 |
| commit | 48f5929604d04484f6e6d2f047e81ee5df127633 (patch) | |
| tree | 78d4ca95da692c211090fc0621d11f9b283ae0db | |
| parent | 4c7749e8c8e50ad146da599eea3a250160c1bc2b (diff) | |
| parent | fdbc8d08a63a3d34b7aebabb2f18a768462a98c4 (diff) | |
| download | rust-48f5929604d04484f6e6d2f047e81ee5df127633.tar.gz rust-48f5929604d04484f6e6d2f047e81ee5df127633.zip | |
Rollup merge of #141658 - lolbinarycat:rustdoc-search-stability-rank-138067, r=GuillaumeGomez
rustdoc search: prefer stable items in search results fixes https://github.com/rust-lang/rust/issues/138067 this does add a new field to the search index, but since we're only listing unstable items instead of adding a boolean flag to every item, it should only increase the search index size of sysroot crates, since those are the only ones using the `staged_api` feature, at least as far as the rust project is concerned.
| -rw-r--r-- | src/librustdoc/formats/cache.rs | 1 | ||||
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustdoc/html/render/search_index.rs | 6 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/rustdoc.d.ts | 3 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 27 | ||||
| -rw-r--r-- | tests/rustdoc-js-std/core-transmute.js | 2 | ||||
| -rw-r--r-- | tests/rustdoc-js-std/transmute-fail.js | 2 | ||||
| -rw-r--r-- | tests/rustdoc-js-std/transmute.js | 2 | ||||
| -rw-r--r-- | tests/rustdoc-js/sort-stability.js | 9 | ||||
| -rw-r--r-- | tests/rustdoc-js/sort-stability.rs | 16 |
10 files changed, 65 insertions, 4 deletions
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 80399cf3842..918b292466d 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -602,6 +602,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It search_type, aliases, deprecation, + is_unstable: item.stability(tcx).map(|x| x.is_unstable()).unwrap_or(false), }; cache.search_index.push(index_item); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a46253237db..95259847075 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -139,6 +139,7 @@ pub(crate) struct IndexItem { pub(crate) search_type: Option<IndexItemFunctionType>, pub(crate) aliases: Box<[Symbol]>, pub(crate) deprecation: Option<Deprecation>, + pub(crate) is_unstable: bool, } /// A type used for the search index. diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e2f86b8a854..93c9df8c049 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -93,6 +93,7 @@ pub(crate) fn build_index( ), aliases: item.attrs.get_doc_aliases(), deprecation: item.deprecation(tcx), + is_unstable: item.stability(tcx).is_some_and(|x| x.is_unstable()), }); } } @@ -655,6 +656,7 @@ pub(crate) fn build_index( let mut parents_backref_queue = VecDeque::new(); let mut functions = String::with_capacity(self.items.len()); let mut deprecated = Vec::with_capacity(self.items.len()); + let mut unstable = Vec::with_capacity(self.items.len()); let mut type_backref_queue = VecDeque::new(); @@ -711,6 +713,9 @@ pub(crate) fn build_index( // bitmasks always use 1-indexing for items, with 0 as the crate itself deprecated.push(u32::try_from(index + 1).unwrap()); } + if item.is_unstable { + unstable.push(u32::try_from(index + 1).unwrap()); + } } for (index, path) in &revert_extra_paths { @@ -749,6 +754,7 @@ pub(crate) fn build_index( crate_data.serialize_field("r", &re_exports)?; crate_data.serialize_field("b", &self.associated_item_disambiguators)?; crate_data.serialize_field("c", &bitmap_to_string(&deprecated))?; + crate_data.serialize_field("u", &bitmap_to_string(&unstable))?; crate_data.serialize_field("e", &bitmap_to_string(&self.empty_desc))?; crate_data.serialize_field("P", ¶m_names)?; if has_aliases { diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index a9589764547..b082b65ab57 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -449,6 +449,8 @@ declare namespace rustdoc { * of `p`) but is used for modules items like free functions. * * `c` is an array of item indices that are deprecated. + * + * `u` is an array of item indices that are unstable. */ type RawSearchIndexCrate = { doc: string, @@ -463,6 +465,7 @@ declare namespace rustdoc { p: Array<[number, string] | [number, string, number] | [number, string, number, number] | [number, string, number, number, string]>, b: Array<[number, String]>, c: string, + u: string, r: Array<[number, number]>, P: Array<[number, string]>, }; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 2caf214ff73..9e422040db0 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1465,6 +1465,11 @@ class DocSearch { */ this.searchIndexEmptyDesc = new Map(); /** + * @type {Map<String, RoaringBitmap>} + */ + this.searchIndexUnstable = new Map(); + + /** * @type {Uint32Array} */ this.functionTypeFingerprint = new Uint32Array(0); @@ -2052,9 +2057,10 @@ class DocSearch { }; const descShardList = [descShard]; - // Deprecated items and items with no description + // Deprecated and unstable items and items with no description this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); + this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u)); let descIndex = 0; /** @@ -3326,6 +3332,25 @@ class DocSearch { return a - b; } + // sort unstable items later + // FIXME: there is some doubt if this is the most effecient way to implement this. + // alternative options include: + // * put is_unstable on each item when the index is built. + // increases memory usage but avoids a hashmap lookup. + // * put is_unstable on each item before sorting. + // better worst case performance but worse average case performance. + a = Number( + // @ts-expect-error + this.searchIndexUnstable.get(aaa.item.crate).contains(aaa.item.bitIndex), + ); + b = Number( + // @ts-expect-error + this.searchIndexUnstable.get(bbb.item.crate).contains(bbb.item.bitIndex), + ); + if (a !== b) { + return a - b; + } + // sort by crate (current crate comes first) a = Number(aaa.item.crate !== preferredCrate); b = Number(bbb.item.crate !== preferredCrate); diff --git a/tests/rustdoc-js-std/core-transmute.js b/tests/rustdoc-js-std/core-transmute.js index 8c9910a32d7..b15f398902c 100644 --- a/tests/rustdoc-js-std/core-transmute.js +++ b/tests/rustdoc-js-std/core-transmute.js @@ -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' }, ], }, ]; diff --git a/tests/rustdoc-js-std/transmute-fail.js b/tests/rustdoc-js-std/transmute-fail.js index ddfb2761948..459e8dc3f00 100644 --- a/tests/rustdoc-js-std/transmute-fail.js +++ b/tests/rustdoc-js-std/transmute-fail.js @@ -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' }, ], }, ]; diff --git a/tests/rustdoc-js-std/transmute.js b/tests/rustdoc-js-std/transmute.js index f52e0ab1436..a85b02e2994 100644 --- a/tests/rustdoc-js-std/transmute.js +++ b/tests/rustdoc-js-std/transmute.js @@ -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' }, ], }, ]; diff --git a/tests/rustdoc-js/sort-stability.js b/tests/rustdoc-js/sort-stability.js new file mode 100644 index 00000000000..8c095619a08 --- /dev/null +++ b/tests/rustdoc-js/sort-stability.js @@ -0,0 +1,9 @@ +const EXPECTED = [ + { + 'query': 'foo', + 'others': [ + {"path": "sort_stability::old", "name": "foo"}, + {"path": "sort_stability::new", "name": "foo"}, + ], + }, +]; diff --git a/tests/rustdoc-js/sort-stability.rs b/tests/rustdoc-js/sort-stability.rs new file mode 100644 index 00000000000..68662bb3aab --- /dev/null +++ b/tests/rustdoc-js/sort-stability.rs @@ -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() {} +} |
