From 351890d682241e4eb9b8a63cddfb22e90567b870 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 15 Mar 2024 17:49:23 -0700 Subject: [PATCH 01/12] rustdoc: clean up formatting --- src/librustdoc/html/static/js/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 875ebe2fc90d4..cbfa503f26060 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -426,7 +426,7 @@ function initSearch(rawSearchIndex) { return c === "," || c === "="; } -/** + /** * Returns `true` if the given `c` character is a path separator. For example * `:` in `a::b` or a whitespace in `a b`. * From 5b44bfda7fc62b2874400e613672aefe5b49aaaa Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 16 Mar 2024 17:50:44 -0700 Subject: [PATCH 02/12] rustdoc-search: shard the search result descriptions The descriptions are, on almost all crates[^1], the majority of the size of the search index, even though they aren't really used for searching. This makes it relatively easy to separate them into their own files. This commit also bumps us to ES8. Out of the browsers we support, all of them support async functions according to caniuse. https://caniuse.com/async-functions [^1]: , a crate with 44MiB of pure names and no descriptions for them, is an outlier and should not be counted. --- .../docker/host-x86_64/mingw-check/Dockerfile | 2 +- src/librustdoc/html/render/mod.rs | 33 +- src/librustdoc/html/render/search_index.rs | 101 ++++- src/librustdoc/html/render/write_shared.rs | 31 +- src/librustdoc/html/static/.eslintrc.js | 2 +- src/librustdoc/html/static/js/main.js | 28 +- src/librustdoc/html/static/js/search.js | 348 ++++++++++-------- src/librustdoc/html/static/js/storage.js | 4 +- src/tools/rustdoc-js/.eslintrc.js | 2 +- src/tools/rustdoc-js/tester.js | 104 ++++-- tests/rustdoc/search-index-summaries.rs | 2 +- 11 files changed, 428 insertions(+), 229 deletions(-) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 30d3a52d82b82..de8db8ee03496 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -56,7 +56,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ /scripts/validate-error-codes.sh && \ reuse --include-submodules lint && \ # Runs checks to ensure that there are no ES5 issues in our JS code. - es-check es6 ../src/librustdoc/html/static/js/*.js && \ + es-check es8 ../src/librustdoc/html/static/js/*.js && \ eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \ eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \ eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6c5040414bced..c1a7593c26f08 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -184,40 +184,15 @@ pub(crate) enum RenderTypeId { impl RenderTypeId { pub fn write_to_string(&self, string: &mut String) { - // (sign, value) - let (sign, id): (bool, u32) = match &self { + let id: i32 = match &self { // 0 is a sentinel, everything else is one-indexed // concrete type - RenderTypeId::Index(idx) if *idx >= 0 => (false, (idx + 1isize).try_into().unwrap()), + RenderTypeId::Index(idx) if *idx >= 0 => (idx + 1isize).try_into().unwrap(), // generic type parameter - RenderTypeId::Index(idx) => (true, (-*idx).try_into().unwrap()), + RenderTypeId::Index(idx) => (*idx).try_into().unwrap(), _ => panic!("must convert render types to indexes before serializing"), }; - // zig-zag encoding - let value: u32 = (id << 1) | (if sign { 1 } else { 0 }); - // Self-terminating hex use capital letters for everything but the - // least significant digit, which is lowercase. For example, decimal 17 - // would be `` Aa `` if zig-zag encoding weren't used. - // - // Zig-zag encoding, however, stores the sign bit as the last bit. - // This means, in the last hexit, 1 is actually `c`, -1 is `b` - // (`a` is the imaginary -0), and, because all the bits are shifted - // by one, `` A` `` is actually 8 and `` Aa `` is -8. - // - // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html - // describes the encoding in more detail. - let mut shift: u32 = 28; - let mut mask: u32 = 0xF0_00_00_00; - while shift < 32 { - let hexit = (value & mask) >> shift; - if hexit != 0 || shift == 0 { - let hex = - char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); - string.push(hex); - } - shift = shift.wrapping_sub(4); - mask = mask >> 4; - } + search_index::write_vlqhex_to_string(id, string); } } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f153a90832910..34a4a89aa7bfa 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -17,12 +17,25 @@ use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; +/// The serialized search description sharded version +/// +/// The `index` is a JSON-encoded list of names and other information. +/// +/// The desc has newlined descriptions, split up by size into 1MiB shards. +/// For example, `(4, "foo\nbar\nbaz\nquux")`. +pub(crate) struct SerializedSearchIndex { + pub(crate) index: String, + pub(crate) desc: Vec<(usize, String)>, +} + +const DESC_INDEX_SHARD_LEN: usize = 1024 * 1024; + /// Builds the search index from the collected metadata pub(crate) fn build_index<'tcx>( krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>, -) -> String { +) -> SerializedSearchIndex { let mut itemid_to_pathid = FxHashMap::default(); let mut primitives = FxHashMap::default(); let mut associated_types = FxHashMap::default(); @@ -318,7 +331,6 @@ pub(crate) fn build_index<'tcx>( .collect::>(); struct CrateData<'a> { - doc: String, items: Vec<&'a IndexItem>, paths: Vec<(ItemType, Vec)>, // The String is alias name and the vec is the list of the elements with this alias. @@ -327,6 +339,9 @@ pub(crate) fn build_index<'tcx>( aliases: &'a BTreeMap>, // Used when a type has more than one impl with an associated item with the same name. associated_item_disambiguators: &'a Vec<(usize, String)>, + // A list of shard lengths encoded as vlqhex. See the comment in write_vlqhex_to_string + // for information on the format. + descindex: String, } struct Paths { @@ -408,7 +423,6 @@ pub(crate) fn build_index<'tcx>( let mut names = Vec::with_capacity(self.items.len()); let mut types = String::with_capacity(self.items.len()); let mut full_paths = Vec::with_capacity(self.items.len()); - let mut descriptions = Vec::with_capacity(self.items.len()); let mut parents = Vec::with_capacity(self.items.len()); let mut functions = String::with_capacity(self.items.len()); let mut deprecated = Vec::with_capacity(self.items.len()); @@ -431,7 +445,6 @@ pub(crate) fn build_index<'tcx>( parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0)); names.push(item.name.as_str()); - descriptions.push(&item.desc); if !item.path.is_empty() { full_paths.push((index, &item.path)); @@ -454,14 +467,12 @@ pub(crate) fn build_index<'tcx>( let has_aliases = !self.aliases.is_empty(); let mut crate_data = serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?; - crate_data.serialize_field("doc", &self.doc)?; crate_data.serialize_field("t", &types)?; crate_data.serialize_field("n", &names)?; - // Serialize as an array of item indices and full paths crate_data.serialize_field("q", &full_paths)?; - crate_data.serialize_field("d", &descriptions)?; crate_data.serialize_field("i", &parents)?; crate_data.serialize_field("f", &functions)?; + crate_data.serialize_field("D", &self.descindex)?; crate_data.serialize_field("c", &deprecated)?; crate_data.serialize_field("p", &paths)?; crate_data.serialize_field("b", &self.associated_item_disambiguators)?; @@ -472,16 +483,46 @@ pub(crate) fn build_index<'tcx>( } } - // Collect the index into a string - format!( + let desc = { + let mut result = Vec::new(); + let mut set = String::new(); + let mut len: usize = 0; + for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { + if set.len() >= DESC_INDEX_SHARD_LEN { + result.push((len, std::mem::replace(&mut set, String::new()))); + len = 0; + } else if len != 0 { + set.push('\n'); + } + set.push_str(&desc); + len += 1; + } + result.push((len, std::mem::replace(&mut set, String::new()))); + result + }; + + let descindex = { + let mut descindex = String::with_capacity(desc.len() * 4); + for &(len, _) in desc.iter() { + write_vlqhex_to_string(len.try_into().unwrap(), &mut descindex); + } + descindex + }; + + assert_eq!(crate_items.len() + 1, desc.iter().map(|(len, _)| *len).sum::()); + + // The index, which is actually used to search, is JSON + // It uses `JSON.parse(..)` to actually load, since JSON + // parses faster than the full JavaScript syntax. + let index = format!( r#"["{}",{}]"#, krate.name(tcx), serde_json::to_string(&CrateData { - doc: crate_doc, items: crate_items, paths: crate_paths, aliases: &aliases, associated_item_disambiguators: &associated_item_disambiguators, + descindex, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. @@ -489,7 +530,45 @@ pub(crate) fn build_index<'tcx>( .replace('\'', r"\'") // We need to escape double quotes for the JSON. .replace("\\\"", "\\\\\"") - ) + ); + SerializedSearchIndex { index, desc } +} + +pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { + let (sign, magnitude): (bool, u32) = + if n >= 0 { (false, n.try_into().unwrap()) } else { (true, (-n).try_into().unwrap()) }; + // zig-zag encoding + let value: u32 = (magnitude << 1) | (if sign { 1 } else { 0 }); + // Self-terminating hex use capital letters for everything but the + // least significant digit, which is lowercase. For example, decimal 17 + // would be `` Aa `` if zig-zag encoding weren't used. + // + // Zig-zag encoding, however, stores the sign bit as the last bit. + // This means, in the last hexit, 1 is actually `c`, -1 is `b` + // (`a` is the imaginary -0), and, because all the bits are shifted + // by one, `` A` `` is actually 8 and `` Aa `` is -8. + // + // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html + // describes the encoding in more detail. + let mut shift: u32 = 28; + let mut mask: u32 = 0xF0_00_00_00; + // first skip leading zeroes + while shift < 32 { + let hexit = (value & mask) >> shift; + if hexit != 0 || shift == 0 { + break; + } + shift = shift.wrapping_sub(4); + mask = mask >> 4; + } + // now write the rest + while shift < 32 { + let hexit = (value & mask) >> shift; + let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); + string.push(hex); + shift = shift.wrapping_sub(4); + mask = mask >> 4; + } } pub(crate) fn get_function_type_for_search<'tcx>( diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index fbd45b2b48ef9..c806bf1cc66f3 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -24,6 +24,7 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::formats::Impl; use crate::html::format::Buffer; +use crate::html::render::search_index::SerializedSearchIndex; use crate::html::render::{AssocItemLink, ImplRenderingParameters}; use crate::html::{layout, static_files}; use crate::visit::DocVisitor; @@ -46,7 +47,7 @@ use crate::{try_err, try_none}; pub(super) fn write_shared( cx: &mut Context<'_>, krate: &Crate, - search_index: String, + search_index: SerializedSearchIndex, options: &RenderOptions, ) -> Result<(), Error> { // Write out the shared files. Note that these are shared among all rustdoc @@ -312,7 +313,7 @@ pub(super) fn write_shared( let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix)); let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst); - all_indexes.push(search_index); + all_indexes.push(search_index.index); krates.push(krate.name(cx.tcx()).to_string()); krates.sort(); @@ -335,6 +336,32 @@ else if (window.initSearch) window.initSearch(searchIndex); Ok(v.into_bytes()) })?; + let search_desc_dir = cx.dst.join(format!("search.desc/{krate}", krate = krate.name(cx.tcx()))); + if Path::new(&search_desc_dir).exists() { + try_err!(std::fs::remove_dir_all(&search_desc_dir), &search_desc_dir); + } + try_err!(std::fs::create_dir_all(&search_desc_dir), &search_desc_dir); + let kratename = krate.name(cx.tcx()).to_string(); + for (i, (_, data)) in search_index.desc.into_iter().enumerate() { + let output_filename = static_files::suffix_path( + &format!("{kratename}-desc-{i}-.js"), + &cx.shared.resource_suffix, + ); + let path = search_desc_dir.join(output_filename); + try_err!( + std::fs::write( + &path, + &format!( + r##"searchState.loadedDescShard({kratename}, {i}, {data})"##, + kratename = serde_json::to_string(&kratename).unwrap(), + data = serde_json::to_string(&data).unwrap(), + ) + .into_bytes() + ), + &path + ); + } + write_invocation_specific("crates.js", &|| { let krates = krates.iter().map(|k| format!("\"{k}\"")).join(","); Ok(format!("window.ALL_CRATES = [{krates}];").into_bytes()) diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index 1a34530c2d16e..a1e9cc6dfa142 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { }, "extends": "eslint:recommended", "parserOptions": { - "ecmaVersion": 2015, + "ecmaVersion": 8, "sourceType": "module" }, "rules": { diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index b9a769a7c6da4..2c1330614b8d8 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -329,6 +329,26 @@ function preLoadCss(cssUrl) { search.innerHTML = "

" + searchState.loadingText + "

"; searchState.showResults(search); }, + descShards: new Map(), + loadDesc: async function({descShard, descIndex}) { + if (descShard.promise === null) { + descShard.promise = new Promise((resolve, reject) => { + descShard.resolve = resolve; + const ds = descShard; + const fname = `${ds.crate}-desc-${ds.shard}-`; + const url = resourcePath( + `search.desc/${descShard.crate}/${fname}`, + ".js", + ); + loadScript(url, reject); + }); + } + const list = await descShard.promise; + return list[descIndex]; + }, + loadedDescShard: function (crate, shard, data) { + this.descShards.get(crate)[shard].resolve(data.split("\n")); + }, }; const toggleAllDocsId = "toggle-all-docs"; @@ -381,7 +401,7 @@ function preLoadCss(cssUrl) { window.location.replace("#" + item.id); }, 0); } - } + }, ); } } @@ -585,7 +605,7 @@ function preLoadCss(cssUrl) { const script = document .querySelector("script[data-ignore-extern-crates]"); const ignoreExternCrates = new Set( - (script ? script.getAttribute("data-ignore-extern-crates") : "").split(",") + (script ? script.getAttribute("data-ignore-extern-crates") : "").split(","), ); for (const lib of libs) { if (lib === window.currentCrate || ignoreExternCrates.has(lib)) { @@ -1098,7 +1118,7 @@ function preLoadCss(cssUrl) { } else { wrapper.style.setProperty( "--popover-arrow-offset", - (wrapperPos.right - pos.right + 4) + "px" + (wrapperPos.right - pos.right + 4) + "px", ); } wrapper.style.visibility = ""; @@ -1680,7 +1700,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm pendingSidebarResizingFrame = false; document.documentElement.style.setProperty( "--resizing-sidebar-width", - desiredSidebarSize + "px" + desiredSidebarSize + "px", ); }, 100); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index cbfa503f26060..2732d6b15436d 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -206,14 +206,14 @@ const editDistanceState = { // insertion this.current[j - 1] + 1, // substitution - this.prev[j - 1] + substitutionCost + this.prev[j - 1] + substitutionCost, ); if ((i > 1) && (j > 1) && (a[aIdx] === b[bIdx - 1]) && (a[aIdx - 1] === b[bIdx])) { // transposition this.current[j] = Math.min( this.current[j], - this.prevPrev[j - 2] + 1 + this.prevPrev[j - 2] + 1, ); } } @@ -856,8 +856,8 @@ function initSearch(rawSearchIndex) { parserState, parserState.userQuery.slice(start, end), generics, - isInGenerics - ) + isInGenerics, + ), ); } } @@ -1295,7 +1295,7 @@ function initSearch(rawSearchIndex) { * * @return {ResultsTable} */ - function execQuery(parsedQuery, filterCrates, currentCrate) { + async function execQuery(parsedQuery, filterCrates, currentCrate) { const results_others = new Map(), results_in_args = new Map(), results_returned = new Map(); @@ -1326,6 +1326,7 @@ function initSearch(rawSearchIndex) { duplicates.add(obj.fullPath); obj.href = res[1]; + obj.desc = result.desc; out.push(obj); if (out.length >= MAX_RESULTS) { break; @@ -1342,9 +1343,9 @@ function initSearch(rawSearchIndex) { * @param {Results} results * @param {boolean} isType * @param {string} preferredCrate - * @returns {[ResultObject]} + * @returns {Promise<[ResultObject]>} */ - function sortResults(results, isType, preferredCrate) { + async function sortResults(results, isType, preferredCrate) { const userQuery = parsedQuery.userQuery; const result_list = []; for (const result of results.values()) { @@ -1352,6 +1353,12 @@ function initSearch(rawSearchIndex) { result.word = searchIndex[result.id].word; result_list.push(result); } + for (const result of result_list) { + result.desc = searchState.loadDesc(result.item); + } + for (const result of result_list) { + result.desc = await result.desc; + } result_list.sort((aaa, bbb) => { let a, b; @@ -1422,8 +1429,8 @@ function initSearch(rawSearchIndex) { } // sort by description (no description goes later) - a = (aaa.item.desc === ""); - b = (bbb.item.desc === ""); + a = (aaa.desc === ""); + b = (bbb.desc === ""); if (a !== b) { return a - b; } @@ -1477,7 +1484,7 @@ function initSearch(rawSearchIndex) { whereClause, mgensIn, solutionCb, - unboxingDepth + unboxingDepth, ) { if (unboxingDepth >= UNBOXING_LIMIT) { return false; @@ -1524,7 +1531,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgens, - unboxingDepth + 1 + unboxingDepth + 1, )) { continue; } @@ -1541,7 +1548,7 @@ function initSearch(rawSearchIndex) { whereClause, mgensScratch, solutionCb, - unboxingDepth + 1 + unboxingDepth + 1, )) { return true; } @@ -1551,7 +1558,7 @@ function initSearch(rawSearchIndex) { whereClause, mgens ? new Map(mgens) : null, solutionCb, - unboxingDepth + 1 + unboxingDepth + 1, )) { return true; } @@ -1625,7 +1632,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgensScratch, - unboxingDepth + unboxingDepth, ); if (!solution) { return false; @@ -1638,7 +1645,7 @@ function initSearch(rawSearchIndex) { whereClause, simplifiedMgens, solutionCb, - unboxingDepth + unboxingDepth, ); if (passesUnification) { return true; @@ -1646,7 +1653,7 @@ function initSearch(rawSearchIndex) { } return false; }, - unboxingDepth + unboxingDepth, ); if (passesUnification) { return true; @@ -1663,7 +1670,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgens, - unboxingDepth + 1 + unboxingDepth + 1, )) { continue; } @@ -1689,7 +1696,7 @@ function initSearch(rawSearchIndex) { whereClause, mgensScratch, solutionCb, - unboxingDepth + 1 + unboxingDepth + 1, ); if (passesUnification) { return true; @@ -1820,7 +1827,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgensIn, - unboxingDepth + unboxingDepth, ) { if (fnType.bindings.size < queryElem.bindings.size) { return false; @@ -1849,7 +1856,7 @@ function initSearch(rawSearchIndex) { // possible solutions return false; }, - unboxingDepth + unboxingDepth, ); return newSolutions; }); @@ -1887,7 +1894,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgens, - unboxingDepth + unboxingDepth, ) { if (unboxingDepth >= UNBOXING_LIMIT) { return false; @@ -1914,7 +1921,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgensTmp, - unboxingDepth + unboxingDepth, ); } else if (fnType.generics.length > 0 || fnType.bindings.size > 0) { const simplifiedGenerics = [ @@ -1926,7 +1933,7 @@ function initSearch(rawSearchIndex) { queryElem, whereClause, mgens, - unboxingDepth + unboxingDepth, ); } return false; @@ -1975,7 +1982,7 @@ function initSearch(rawSearchIndex) { elem, whereClause, mgens, - unboxingDepth + 1 + unboxingDepth + 1, ); } if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 && @@ -1989,7 +1996,7 @@ function initSearch(rawSearchIndex) { elem, whereClause, mgens, - unboxingDepth + unboxingDepth, ); } } @@ -2007,7 +2014,7 @@ function initSearch(rawSearchIndex) { return 0; } const maxPathEditDistance = Math.floor( - contains.reduce((acc, next) => acc + next.length, 0) / 3 + contains.reduce((acc, next) => acc + next.length, 0) / 3, ); let ret_dist = maxPathEditDistance + 1; const path = ty.path.split("::"); @@ -2066,7 +2073,8 @@ function initSearch(rawSearchIndex) { crate: item.crate, name: item.name, path: item.path, - desc: item.desc, + descShard: item.descShard, + descIndex: item.descIndex, ty: item.ty, parent: item.parent, type: item.type, @@ -2192,7 +2200,7 @@ function initSearch(rawSearchIndex) { results_others, results_in_args, results_returned, - maxEditDistance + maxEditDistance, ) { if (!row || (filterCrates !== null && row.crate !== filterCrates)) { return; @@ -2204,7 +2212,7 @@ function initSearch(rawSearchIndex) { // atoms in the function not present in the query const tfpDist = compareTypeFingerprints( fullId, - parsedQuery.typeFingerprint + parsedQuery.typeFingerprint, ); if (tfpDist !== null) { const in_args = row.type && row.type.inputs @@ -2276,7 +2284,7 @@ function initSearch(rawSearchIndex) { const tfpDist = compareTypeFingerprints( row.id, - parsedQuery.typeFingerprint + parsedQuery.typeFingerprint, ); if (tfpDist === null) { return; @@ -2298,10 +2306,10 @@ function initSearch(rawSearchIndex) { row.type.where_clause, mgens, null, - 0 // unboxing depth + 0, // unboxing depth ); }, - 0 // unboxing depth + 0, // unboxing depth )) { return; } @@ -2419,7 +2427,7 @@ function initSearch(rawSearchIndex) { } return [typeNameIdMap.get(name).id, constraints]; - }) + }), ); } @@ -2446,7 +2454,7 @@ function initSearch(rawSearchIndex) { results_others, results_in_args, results_returned, - maxEditDistance + maxEditDistance, ); } } @@ -2478,9 +2486,9 @@ function initSearch(rawSearchIndex) { } const ret = createQueryResults( - sortResults(results_in_args, true, currentCrate), - sortResults(results_returned, true, currentCrate), - sortResults(results_others, false, currentCrate), + await sortResults(results_in_args, true, currentCrate), + await sortResults(results_returned, true, currentCrate), + await sortResults(results_others, false, currentCrate), parsedQuery); handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates, currentCrate); if (parsedQuery.error !== null && ret.others.length !== 0) { @@ -2581,14 +2589,14 @@ function initSearch(rawSearchIndex) { * @param {ParsedQuery} query * @param {boolean} display - True if this is the active tab */ - function addTab(array, query, display) { + async function addTab(array, query, display) { const extraClass = display ? " active" : ""; const output = document.createElement("div"); if (array.length > 0) { output.className = "search-results " + extraClass; - array.forEach(item => { + for (const item of array) { const name = item.name; const type = itemTypes[item.ty]; const longType = longItemTypes[item.ty]; @@ -2624,7 +2632,7 @@ ${item.displayPath}${name}\ link.appendChild(description); output.appendChild(link); - }); + } } else if (query.error === null) { output.className = "search-failed" + extraClass; output.innerHTML = "No results :(
" + @@ -2666,7 +2674,7 @@ ${item.displayPath}${name}\ * @param {boolean} go_to_first * @param {string} filterCrates */ - function showResults(results, go_to_first, filterCrates) { + async function showResults(results, go_to_first, filterCrates) { const search = searchState.outputElement(); if (go_to_first || (results.others.length === 1 && getSettingValue("go-to-only-result") === "true") @@ -2699,9 +2707,9 @@ ${item.displayPath}${name}\ currentResults = results.query.userQuery; - const ret_others = addTab(results.others, results.query, true); - const ret_in_args = addTab(results.in_args, results.query, false); - const ret_returned = addTab(results.returned, results.query, false); + const ret_others = await addTab(results.others, results.query, true); + const ret_in_args = await addTab(results.in_args, results.query, false); + const ret_returned = await addTab(results.returned, results.query, false); // Navigate to the relevant tab if the current tab is empty, like in case users search // for "-> String". If they had selected another tab previously, they have to click on @@ -2822,7 +2830,7 @@ ${item.displayPath}${name}\ * and display the results. * @param {boolean} [forced] */ - function search(forced) { + async function search(forced) { const query = parseQuery(searchState.input.value.trim()); let filterCrates = getFilterCrates(); @@ -2850,8 +2858,8 @@ ${item.displayPath}${name}\ // recent search query is added to the browser history. updateSearchHistory(buildUrl(query.original, filterCrates)); - showResults( - execQuery(query, filterCrates, window.currentCrate), + await showResults( + await execQuery(query, filterCrates, window.currentCrate), params.go_to_first, filterCrates); } @@ -2920,7 +2928,7 @@ ${item.displayPath}${name}\ pathIndex = type[PATH_INDEX_DATA]; generics = buildItemSearchTypeAll( type[GENERICS_DATA], - lowercasePaths + lowercasePaths, ); if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) { bindings = new Map(type[BINDINGS_DATA].map(binding => { @@ -3030,101 +3038,49 @@ ${item.displayPath}${name}\ * The raw function search type format is generated using serde in * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string * - * @param {{ - * string: string, - * offset: number, - * backrefQueue: FunctionSearchType[] - * }} itemFunctionDecoder * @param {Array<{name: string, ty: number}>} lowercasePaths - * @param {Map} * * @return {null|FunctionSearchType} */ - function buildFunctionSearchType(itemFunctionDecoder, lowercasePaths) { - const c = itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset); - itemFunctionDecoder.offset += 1; - const [zero, ua, la, ob, cb] = ["0", "@", "`", "{", "}"].map(c => c.charCodeAt(0)); - // `` ` `` is used as a sentinel because it's fewer bytes than `null`, and decodes to zero - // `0` is a backref - if (c === la) { - return null; - } - // sixteen characters after "0" are backref - if (c >= zero && c < ua) { - return itemFunctionDecoder.backrefQueue[c - zero]; - } - if (c !== ob) { - throw ["Unexpected ", c, " in function: expected ", "{", "; this is a bug"]; - } - // call after consuming `{` - function decodeList() { - let c = itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset); - const ret = []; - while (c !== cb) { - ret.push(decode()); - c = itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset); - } - itemFunctionDecoder.offset += 1; // eat cb - return ret; - } - // consumes and returns a list or integer - function decode() { - let n = 0; - let c = itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset); - if (c === ob) { - itemFunctionDecoder.offset += 1; - return decodeList(); - } - while (c < la) { - n = (n << 4) | (c & 0xF); - itemFunctionDecoder.offset += 1; - c = itemFunctionDecoder.string.charCodeAt(itemFunctionDecoder.offset); - } - // last character >= la - n = (n << 4) | (c & 0xF); - const [sign, value] = [n & 1, n >> 1]; - itemFunctionDecoder.offset += 1; - return sign ? -value : value; - } - const functionSearchType = decodeList(); - const INPUTS_DATA = 0; - const OUTPUT_DATA = 1; - let inputs, output; - if (typeof functionSearchType[INPUTS_DATA] === "number") { - inputs = [buildItemSearchType(functionSearchType[INPUTS_DATA], lowercasePaths)]; - } else { - inputs = buildItemSearchTypeAll( - functionSearchType[INPUTS_DATA], - lowercasePaths - ); - } - if (functionSearchType.length > 1) { - if (typeof functionSearchType[OUTPUT_DATA] === "number") { - output = [buildItemSearchType(functionSearchType[OUTPUT_DATA], lowercasePaths)]; + function buildFunctionSearchTypeCallback(lowercasePaths) { + return functionSearchType => { + if (functionSearchType === 0) { + return null; + } + const INPUTS_DATA = 0; + const OUTPUT_DATA = 1; + let inputs, output; + if (typeof functionSearchType[INPUTS_DATA] === "number") { + inputs = [buildItemSearchType(functionSearchType[INPUTS_DATA], lowercasePaths)]; } else { - output = buildItemSearchTypeAll( - functionSearchType[OUTPUT_DATA], - lowercasePaths + inputs = buildItemSearchTypeAll( + functionSearchType[INPUTS_DATA], + lowercasePaths, ); } - } else { - output = []; - } - const where_clause = []; - const l = functionSearchType.length; - for (let i = 2; i < l; ++i) { - where_clause.push(typeof functionSearchType[i] === "number" - ? [buildItemSearchType(functionSearchType[i], lowercasePaths)] - : buildItemSearchTypeAll(functionSearchType[i], lowercasePaths)); - } - const ret = { - inputs, output, where_clause, + if (functionSearchType.length > 1) { + if (typeof functionSearchType[OUTPUT_DATA] === "number") { + output = [buildItemSearchType(functionSearchType[OUTPUT_DATA], lowercasePaths)]; + } else { + output = buildItemSearchTypeAll( + functionSearchType[OUTPUT_DATA], + lowercasePaths, + ); + } + } else { + output = []; + } + const where_clause = []; + const l = functionSearchType.length; + for (let i = 2; i < l; ++i) { + where_clause.push(typeof functionSearchType[i] === "number" + ? [buildItemSearchType(functionSearchType[i], lowercasePaths)] + : buildItemSearchTypeAll(functionSearchType[i], lowercasePaths)); + } + return { + inputs, output, where_clause, + }; }; - itemFunctionDecoder.backrefQueue.unshift(ret); - if (itemFunctionDecoder.backrefQueue.length > 16) { - itemFunctionDecoder.backrefQueue.pop(); - } - return ret; } /** @@ -3245,6 +3201,68 @@ ${item.displayPath}${name}\ return functionTypeFingerprint[(fullId * 4) + 3]; } + class VlqHexDecoder { + constructor(string, cons) { + this.string = string; + this.cons = cons; + this.offset = 0; + this.backrefQueue = []; + } + // call after consuming `{` + decodeList() { + const cb = "}".charCodeAt(0); + let c = this.string.charCodeAt(this.offset); + const ret = []; + while (c !== cb) { + ret.push(this.decode()); + c = this.string.charCodeAt(this.offset); + } + this.offset += 1; // eat cb + return ret; + } + // consumes and returns a list or integer + decode() { + const [ob, la] = ["{", "`"].map(c => c.charCodeAt(0)); + let n = 0; + let c = this.string.charCodeAt(this.offset); + if (c === ob) { + this.offset += 1; + return this.decodeList(); + } + while (c < la) { + n = (n << 4) | (c & 0xF); + this.offset += 1; + c = this.string.charCodeAt(this.offset); + } + // last character >= la + n = (n << 4) | (c & 0xF); + const [sign, value] = [n & 1, n >> 1]; + this.offset += 1; + return sign ? -value : value; + } + next() { + const c = this.string.charCodeAt(this.offset); + const [zero, ua, la] = ["0", "@", "`"].map(c => c.charCodeAt(0)); + // sixteen characters after "0" are backref + if (c >= zero && c < ua) { + this.offset += 1; + return this.backrefQueue[c - zero]; + } + // special exception: 0 doesn't use backref encoding + // it's already one character, and it's always nullish + if (c === la) { + this.offset += 1; + return this.cons(0); + } + const result = this.cons(this.decode()); + this.backrefQueue.unshift(result); + if (this.backrefQueue.length > 16) { + this.backrefQueue.pop(); + } + return result; + } + } + /** * Convert raw search index into in-memory search index. * @@ -3271,18 +3289,32 @@ ${item.displayPath}${name}\ id = 0; for (const [crate, crateCorpus] of rawSearchIndex) { + // a string representing the lengths of each description shard + // a string representing the list of function types + const itemDescShardDecoder = new VlqHexDecoder(crateCorpus.D, noop => noop); + let descShard = { + crate, + shard: 0, + start: 0, + len: itemDescShardDecoder.next(), + promise: null, + resolve: null, + }; + const descShardList = [ descShard ]; + // This object should have exactly the same set of fields as the "row" // object defined below. Your JavaScript runtime will thank you. // https://mathiasbynens.be/notes/shapes-ics const crateRow = { - crate: crate, + crate, ty: 3, // == ExternCrate name: crate, path: "", - desc: crateCorpus.doc, + descShard, + descIndex: 0, parent: undefined, type: null, - id: id, + id, word: crate, normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""), deprecated: null, @@ -3302,16 +3334,8 @@ ${item.displayPath}${name}\ // i.e. if indices 4 and 11 are present, but 5-10 and 12-13 are not present, // 5-10 will fall back to the path for 4 and 12-13 will fall back to the path for 11 const itemPaths = new Map(crateCorpus.q); - // an array of (String) descriptions - const itemDescs = crateCorpus.d; // an array of (Number) the parent path index + 1 to `paths`, or 0 if none const itemParentIdxs = crateCorpus.i; - // a string representing the list of function types - const itemFunctionDecoder = { - string: crateCorpus.f, - offset: 0, - backrefQueue: [], - }; // an array of (Number) indices for the deprecated items const deprecatedItems = new Set(crateCorpus.c); // an array of (Number) indices for the deprecated items @@ -3326,6 +3350,12 @@ ${item.displayPath}${name}\ // an array of [{name: String, ty: Number}] const lowercasePaths = []; + // a string representing the list of function types + const itemFunctionDecoder = new VlqHexDecoder( + crateCorpus.f, + buildFunctionSearchTypeCallback(lowercasePaths), + ); + // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = paths.length; @@ -3353,13 +3383,26 @@ ${item.displayPath}${name}\ // faster analysis operations lastPath = ""; len = itemTypes.length; + let descIndex = 1; for (let i = 0; i < len; ++i) { + if (descIndex >= descShard.len) { + descShard = { + crate, + shard: descShard.shard + 1, + start: descShard.start + descShard.len, + len: itemDescShardDecoder.next(), + promise: null, + resolve: null, + }; + descIndex = 0; + descShardList.push(descShard); + } let word = ""; if (typeof itemNames[i] === "string") { word = itemNames[i].toLowerCase(); } const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; - const type = buildFunctionSearchType(itemFunctionDecoder, lowercasePaths); + const type = itemFunctionDecoder.next(); if (type !== null) { if (type) { const fp = functionTypeFingerprint.subarray(id * 4, (id + 1) * 4); @@ -3380,14 +3423,15 @@ ${item.displayPath}${name}\ // This object should have exactly the same set of fields as the "crateRow" // object defined above. const row = { - crate: crate, + crate, ty: itemTypes.charCodeAt(i) - charA, name: itemNames[i], - path: path, - desc: itemDescs[i], + path, + descShard, + descIndex, parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined, type, - id: id, + id, word, normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""), deprecated: deprecatedItems.has(i), @@ -3396,6 +3440,7 @@ ${item.displayPath}${name}\ id += 1; searchIndex.push(row); lastPath = row.path; + descIndex += 1; } if (aliases) { @@ -3419,6 +3464,7 @@ ${item.displayPath}${name}\ } } currentIndex += itemTypes.length; + searchState.descShards.set(crate, descShardList); } // Drop the (rather large) hash table used for reusing function items TYPES_POOL = new Map(); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index bda7b3c647e7e..73c543567c078 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -211,14 +211,14 @@ function updateSidebarWidth() { if (desktopSidebarWidth && desktopSidebarWidth !== "null") { document.documentElement.style.setProperty( "--desktop-sidebar-width", - desktopSidebarWidth + "px" + desktopSidebarWidth + "px", ); } const srcSidebarWidth = getSettingValue("src-sidebar-width"); if (srcSidebarWidth && srcSidebarWidth !== "null") { document.documentElement.style.setProperty( "--src-sidebar-width", - srcSidebarWidth + "px" + srcSidebarWidth + "px", ); } } diff --git a/src/tools/rustdoc-js/.eslintrc.js b/src/tools/rustdoc-js/.eslintrc.js index 4ab3a31573309..b9d0e251c242b 100644 --- a/src/tools/rustdoc-js/.eslintrc.js +++ b/src/tools/rustdoc-js/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { }, "extends": "eslint:recommended", "parserOptions": { - "ecmaVersion": 2015, + "ecmaVersion": 8, "sourceType": "module" }, "rules": { diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 86881ef362e9f..ae4121cc03f51 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -1,3 +1,4 @@ +/* global globalThis */ const fs = require("fs"); const path = require("path"); @@ -133,7 +134,7 @@ function valueCheck(fullPath, expected, result, error_text, queryName) { expected_value, result.get(key), error_text, - queryName + queryName, ); } else { error_text.push(`${queryName}==> EXPECTED has extra key in map from field ` + @@ -212,11 +213,11 @@ function runParser(query, expected, parseQuery, queryName) { return error_text; } -function runSearch(query, expected, doSearch, loadedFile, queryName) { +async function runSearch(query, expected, doSearch, loadedFile, queryName) { const ignore_order = loadedFile.ignore_order; const exact_check = loadedFile.exact_check; - const results = doSearch(query, loadedFile.FILTER_CRATE); + const results = await doSearch(query, loadedFile.FILTER_CRATE); const error_text = []; for (const key in expected) { @@ -238,7 +239,7 @@ function runSearch(query, expected, doSearch, loadedFile, queryName) { } let prev_pos = -1; - entry.forEach((elem, index) => { + for (const [index, elem] of entry.entries()) { const entry_pos = lookForEntry(elem, results[key]); if (entry_pos === -1) { error_text.push(queryName + "==> Result not found in '" + key + "': '" + @@ -260,13 +261,13 @@ function runSearch(query, expected, doSearch, loadedFile, queryName) { } else { prev_pos = entry_pos; } - }); + } } return error_text; } -function runCorrections(query, corrections, getCorrections, loadedFile) { - const qc = getCorrections(query, loadedFile.FILTER_CRATE); +async function runCorrections(query, corrections, getCorrections, loadedFile) { + const qc = await getCorrections(query, loadedFile.FILTER_CRATE); const error_text = []; if (corrections === null) { @@ -299,18 +300,27 @@ function checkResult(error_text, loadedFile, displaySuccess) { return 1; } -function runCheckInner(callback, loadedFile, entry, getCorrections, extra) { +async function runCheckInner(callback, loadedFile, entry, getCorrections, extra) { if (typeof entry.query !== "string") { console.log("FAILED"); console.log("==> Missing `query` field"); return false; } - let error_text = callback(entry.query, entry, extra ? "[ query `" + entry.query + "`]" : ""); + let error_text = await callback( + entry.query, + entry, + extra ? "[ query `" + entry.query + "`]" : "", + ); if (checkResult(error_text, loadedFile, false) !== 0) { return false; } if (entry.correction !== undefined) { - error_text = runCorrections(entry.query, entry.correction, getCorrections, loadedFile); + error_text = await runCorrections( + entry.query, + entry.correction, + getCorrections, + loadedFile, + ); if (checkResult(error_text, loadedFile, false) !== 0) { return false; } @@ -318,16 +328,16 @@ function runCheckInner(callback, loadedFile, entry, getCorrections, extra) { return true; } -function runCheck(loadedFile, key, getCorrections, callback) { +async function runCheck(loadedFile, key, getCorrections, callback) { const expected = loadedFile[key]; if (Array.isArray(expected)) { for (const entry of expected) { - if (!runCheckInner(callback, loadedFile, entry, getCorrections, true)) { + if (!await runCheckInner(callback, loadedFile, entry, getCorrections, true)) { return 1; } } - } else if (!runCheckInner(callback, loadedFile, expected, getCorrections, false)) { + } else if (!await runCheckInner(callback, loadedFile, expected, getCorrections, false)) { return 1; } console.log("OK"); @@ -338,7 +348,7 @@ function hasCheck(content, checkName) { return content.startsWith(`const ${checkName}`) || content.includes(`\nconst ${checkName}`); } -function runChecks(testFile, doSearch, parseQuery, getCorrections) { +async function runChecks(testFile, doSearch, parseQuery, getCorrections) { let checkExpected = false; let checkParsed = false; let testFileContent = readFile(testFile); @@ -367,12 +377,12 @@ function runChecks(testFile, doSearch, parseQuery, getCorrections) { let res = 0; if (checkExpected) { - res += runCheck(loadedFile, "EXPECTED", getCorrections, (query, expected, text) => { + res += await runCheck(loadedFile, "EXPECTED", getCorrections, (query, expected, text) => { return runSearch(query, expected, doSearch, loadedFile, text); }); } if (checkParsed) { - res += runCheck(loadedFile, "PARSED", getCorrections, (query, expected, text) => { + res += await runCheck(loadedFile, "PARSED", getCorrections, (query, expected, text) => { return runParser(query, expected, parseQuery, text); }); } @@ -393,6 +403,35 @@ function loadSearchJS(doc_folder, resource_suffix) { const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js"); const searchIndex = require(searchIndexJs); + globalThis.searchState = { + descShards: new Map(), + loadDesc: async function({descShard, descIndex}) { + if (descShard.promise === null) { + descShard.promise = new Promise((resolve, reject) => { + descShard.resolve = resolve; + const ds = descShard; + const fname = `${ds.crate}-desc-${ds.shard}-${resource_suffix}.js`; + fs.readFile( + `${doc_folder}/search.desc/${descShard.crate}/${fname}`, + (err, data) => { + if (err) { + reject(err); + } else { + eval(data.toString("utf8")); + } + }, + ); + }); + } + const list = await descShard.promise; + return list[descIndex]; + }, + loadedDescShard: function (crate, shard, data) { + //console.log(this.descShards); + this.descShards.get(crate)[shard].resolve(data.split("\n")); + }, + }; + const staticFiles = path.join(doc_folder, "static.files"); const searchJs = fs.readdirSync(staticFiles).find(f => f.match(/search.*\.js$/)); const searchModule = require(path.join(staticFiles, searchJs)); @@ -474,7 +513,7 @@ function parseOptions(args) { return null; } -function main(argv) { +async function main(argv) { const opts = parseOptions(argv.slice(2)); if (opts === null) { return 1; @@ -482,7 +521,7 @@ function main(argv) { const parseAndSearch = loadSearchJS( opts["doc_folder"], - opts["resource_suffix"] + opts["resource_suffix"], ); let errors = 0; @@ -494,21 +533,34 @@ function main(argv) { }; if (opts["test_file"].length !== 0) { - opts["test_file"].forEach(file => { + for (const file of opts["test_file"]) { process.stdout.write(`Testing ${file} ... `); - errors += runChecks(file, doSearch, parseAndSearch.parseQuery, getCorrections); - }); + errors += await runChecks(file, doSearch, parseAndSearch.parseQuery, getCorrections); + } } else if (opts["test_folder"].length !== 0) { - fs.readdirSync(opts["test_folder"]).forEach(file => { + for (const file of fs.readdirSync(opts["test_folder"])) { if (!file.endsWith(".js")) { - return; + continue; } process.stdout.write(`Testing ${file} ... `); - errors += runChecks(path.join(opts["test_folder"], file), doSearch, + errors += await runChecks(path.join(opts["test_folder"], file), doSearch, parseAndSearch.parseQuery, getCorrections); - }); + } } return errors > 0 ? 1 : 0; } -process.exit(main(process.argv)); +main(process.argv).catch(e => { + console.log(e); + process.exit(1); +}).then(x => process.exit(x)); + +process.on("beforeExit", () => { + console.log("process did not complete"); + process.exit(1); +}); + +/*process.on("uncaughtException", (err) => { + console.log(`Uncaught Exception: ${err.message}`); + process.exit(1); +});*/ diff --git a/tests/rustdoc/search-index-summaries.rs b/tests/rustdoc/search-index-summaries.rs index efd366405bfeb..529b42d0ca903 100644 --- a/tests/rustdoc/search-index-summaries.rs +++ b/tests/rustdoc/search-index-summaries.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @hasraw 'search-index.js' 'Foo short link.' +// @hasraw 'search.desc/foo/foo-desc-0-.js' 'Foo short link.' // @!hasraw - 'www.example.com' // @!hasraw - 'More Foo.' From 2e368bfe9ec1ace30b43673d8b30a7f388b86e28 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 16 Mar 2024 23:01:47 -0700 Subject: [PATCH 03/12] Fix style errors --- src/librustdoc/html/static/js/main.js | 2 +- src/tools/rustdoc-js/tester.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 2c1330614b8d8..eff3dc27911bf 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -346,7 +346,7 @@ function preLoadCss(cssUrl) { const list = await descShard.promise; return list[descIndex]; }, - loadedDescShard: function (crate, shard, data) { + loadedDescShard: function(crate, shard, data) { this.descShards.get(crate)[shard].resolve(data.split("\n")); }, }; diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index ae4121cc03f51..1af2f44c230d6 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -426,7 +426,7 @@ function loadSearchJS(doc_folder, resource_suffix) { const list = await descShard.promise; return list[descIndex]; }, - loadedDescShard: function (crate, shard, data) { + loadedDescShard: function(crate, shard, data) { //console.log(this.descShards); this.descShards.get(crate)[shard].resolve(data.split("\n")); }, From e860b9cd24ba7555c0aba8e850985c30a837335e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 18 Mar 2024 13:39:35 -0700 Subject: [PATCH 04/12] Use promise.all to load sorted results in parallel --- src/librustdoc/html/static/js/search.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 2732d6b15436d..15da5bf96b2ca 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2485,10 +2485,15 @@ function initSearch(rawSearchIndex) { innerRunQuery(); } + const [sorted_in_args, sorted_returned, sorted_others] = await Promise.all([ + sortResults(results_in_args, true, currentCrate), + sortResults(results_returned, true, currentCrate), + sortResults(results_others, false, currentCrate), + ]); const ret = createQueryResults( - await sortResults(results_in_args, true, currentCrate), - await sortResults(results_returned, true, currentCrate), - await sortResults(results_others, false, currentCrate), + sorted_in_args, + sorted_returned, + sorted_others, parsedQuery); handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates, currentCrate); if (parsedQuery.error !== null && ret.others.length !== 0) { From 28db4ccda76ffd2ce4c36912a194979a7ce2ef8d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 21 Mar 2024 17:19:39 -0700 Subject: [PATCH 05/12] rustdoc-search: compressed bitmap to sort, then load desc This adds a bit more data than "pure sharding" by including information about which items have no description at all. This way, it can sort the results, then truncate, then finally download the description. With the "e" bitmap: 2380KiB Without the "e" bitmap: 2364KiB --- Cargo.lock | 2 + src/librustdoc/Cargo.toml | 2 + src/librustdoc/html/render/search_index.rs | 233 ++++++++++++++++++++- src/librustdoc/html/static/js/search.js | 190 ++++++++++++++--- src/tools/rustdoc-js/tester.js | 5 - 5 files changed, 395 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16aed3dc49ca0..1e7ef0cca9bc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4741,6 +4741,8 @@ version = "0.0.0" dependencies = [ "arrayvec", "askama", + "base64", + "byteorder", "expect-test", "indexmap", "itertools 0.12.1", diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index bd0fbef998b2b..44ba2a8c0153e 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,8 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } askama = { version = "0.12", default-features = false, features = ["config"] } +base64 = "0.21.7" +byteorder = "1.5" itertools = "0.12" indexmap = "2" minifier = "0.3.0" diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 34a4a89aa7bfa..2ec22df0b434f 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1,6 +1,7 @@ use std::collections::hash_map::Entry; use std::collections::{BTreeMap, VecDeque}; +use base64::prelude::*; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; @@ -21,14 +22,14 @@ use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, Re /// /// The `index` is a JSON-encoded list of names and other information. /// -/// The desc has newlined descriptions, split up by size into 1MiB shards. +/// The desc has newlined descriptions, split up by size into 128KiB shards. /// For example, `(4, "foo\nbar\nbaz\nquux")`. pub(crate) struct SerializedSearchIndex { pub(crate) index: String, pub(crate) desc: Vec<(usize, String)>, } -const DESC_INDEX_SHARD_LEN: usize = 1024 * 1024; +const DESC_INDEX_SHARD_LEN: usize = 128 * 1024; /// Builds the search index from the collected metadata pub(crate) fn build_index<'tcx>( @@ -342,6 +343,8 @@ pub(crate) fn build_index<'tcx>( // A list of shard lengths encoded as vlqhex. See the comment in write_vlqhex_to_string // for information on the format. descindex: String, + // A list of items with no description. This is eventually turned into a bitmap. + emptydesc: Vec, } struct Paths { @@ -456,7 +459,8 @@ pub(crate) fn build_index<'tcx>( } if item.deprecation.is_some() { - deprecated.push(index); + // bitmasks always use 1-indexing for items, with 0 as the crate itself + deprecated.push(u32::try_from(index + 1).unwrap()); } } @@ -473,9 +477,18 @@ pub(crate) fn build_index<'tcx>( crate_data.serialize_field("i", &parents)?; crate_data.serialize_field("f", &functions)?; crate_data.serialize_field("D", &self.descindex)?; - crate_data.serialize_field("c", &deprecated)?; crate_data.serialize_field("p", &paths)?; crate_data.serialize_field("b", &self.associated_item_disambiguators)?; + let mut buf = Vec::new(); + let mut strbuf = String::new(); + write_bitmap_to_bytes(&deprecated, &mut buf).unwrap(); + BASE64_STANDARD.encode_string(&buf, &mut strbuf); + crate_data.serialize_field("c", &strbuf)?; + strbuf.clear(); + buf.clear(); + write_bitmap_to_bytes(&self.emptydesc, &mut buf).unwrap(); + BASE64_STANDARD.encode_string(&buf, &mut strbuf); + crate_data.serialize_field("e", &strbuf)?; if has_aliases { crate_data.serialize_field("a", &self.aliases)?; } @@ -483,11 +496,18 @@ pub(crate) fn build_index<'tcx>( } } - let desc = { + let (emptydesc, desc) = { + let mut emptydesc = Vec::new(); let mut result = Vec::new(); let mut set = String::new(); let mut len: usize = 0; + let mut itemindex: u32 = 0; for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { + if desc == "" { + emptydesc.push(itemindex); + itemindex += 1; + continue; + } if set.len() >= DESC_INDEX_SHARD_LEN { result.push((len, std::mem::replace(&mut set, String::new()))); len = 0; @@ -496,9 +516,10 @@ pub(crate) fn build_index<'tcx>( } set.push_str(&desc); len += 1; + itemindex += 1; } result.push((len, std::mem::replace(&mut set, String::new()))); - result + (emptydesc, result) }; let descindex = { @@ -509,7 +530,10 @@ pub(crate) fn build_index<'tcx>( descindex }; - assert_eq!(crate_items.len() + 1, desc.iter().map(|(len, _)| *len).sum::()); + assert_eq!( + crate_items.len() + 1, + desc.iter().map(|(len, _)| *len).sum::() + emptydesc.len() + ); // The index, which is actually used to search, is JSON // It uses `JSON.parse(..)` to actually load, since JSON @@ -523,6 +547,7 @@ pub(crate) fn build_index<'tcx>( aliases: &aliases, associated_item_disambiguators: &associated_item_disambiguators, descindex, + emptydesc, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. @@ -571,6 +596,200 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { } } +// checked against roaring-rs in +// https://gitlab.com/notriddle/roaring-test +pub fn write_bitmap_to_bytes(domain: &[u32], mut out: impl std::io::Write) -> std::io::Result<()> { + // https://arxiv.org/pdf/1603.06549.pdf + let mut keys = Vec::::new(); + let mut containers = Vec::::new(); + enum Container { + /// number of ones, bits + Bits(Box<[u64; 1024]>), + /// list of entries + Array(Vec), + /// list of (start, len-1) + Run(Vec<(u16, u16)>), + } + impl Container { + fn popcount(&self) -> u32 { + match self { + Container::Bits(bits) => bits.iter().copied().map(|x| x.count_ones()).sum(), + Container::Array(array) => { + array.len().try_into().expect("array can't be bigger than 2**32") + } + Container::Run(runs) => { + runs.iter().copied().map(|(_, lenm1)| u32::from(lenm1) + 1).sum() + } + } + } + fn push(&mut self, value: u16) { + match self { + Container::Bits(bits) => bits[value as usize >> 6] |= 1 << (value & 0x3F), + Container::Array(array) => { + array.push(value); + if array.len() >= 4096 { + let array = std::mem::replace(array, Vec::new()); + *self = Container::Bits(Box::new([0; 1024])); + for value in array { + self.push(value); + } + } + } + Container::Run(runs) => { + if let Some(r) = runs.last_mut() + && r.0 + r.1 + 1 == value + { + r.1 += 1; + } else { + runs.push((value, 0)); + } + } + } + } + fn try_make_run(&mut self) -> bool { + match self { + Container::Bits(bits) => { + let mut r: u64 = 0; + for (i, chunk) in bits.iter().copied().enumerate() { + let next_chunk = + i.checked_add(1).and_then(|i| bits.get(i)).copied().unwrap_or(0); + r += !chunk & u64::from((chunk << 1).count_ones()); + r += !next_chunk & u64::from((chunk >> 63).count_ones()); + } + if (2 + 4 * r) < 8192 { + let bits = std::mem::replace(bits, Box::new([0; 1024])); + *self = Container::Run(Vec::new()); + for (i, bits) in bits.iter().copied().enumerate() { + if bits == 0 { + continue; + } + for j in 0..64 { + let value = (u16::try_from(i).unwrap() << 6) | j; + if bits & (1 << j) != 0 { + self.push(value); + } + } + } + true + } else { + false + } + } + Container::Array(array) if array.len() <= 5 => false, + Container::Array(array) => { + let mut r = 0; + let mut prev = None; + for value in array.iter().copied() { + if value.checked_sub(1) != prev { + r += 1; + } + prev = Some(value); + } + if 2 + 4 * r < 2 * array.len() + 2 { + let array = std::mem::replace(array, Vec::new()); + *self = Container::Run(Vec::new()); + for value in array { + self.push(value); + } + true + } else { + false + } + } + Container::Run(_) => true, + } + } + } + let mut key: u16; + let mut domain_iter = domain.into_iter().copied().peekable(); + let mut has_run = false; + while let Some(entry) = domain_iter.next() { + key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); + let value: u16 = (entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit"); + let mut container = Container::Array(vec![value]); + while let Some(entry) = domain_iter.peek().copied() { + let entry_key: u16 = + (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); + if entry_key != key { + break; + } + domain_iter.next().expect("peeking just succeeded"); + container + .push((entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit")); + } + keys.push(key); + has_run = container.try_make_run() || has_run; + containers.push(container); + } + // https://github.com/RoaringBitmap/RoaringFormatSpec + use byteorder::{WriteBytesExt, LE}; + const SERIAL_COOKIE_NO_RUNCONTAINER: u32 = 12346; + const SERIAL_COOKIE: u32 = 12347; + const NO_OFFSET_THRESHOLD: u32 = 4; + let size: u32 = containers.len().try_into().unwrap(); + let start_offset = if has_run { + out.write_u32::(SERIAL_COOKIE | ((size - 1) << 16))?; + for set in containers.chunks(8) { + let mut b = 0; + for (i, container) in set.iter().enumerate() { + if matches!(container, &Container::Run(..)) { + b |= 1 << i; + } + } + out.write_u8(b)?; + } + if size < NO_OFFSET_THRESHOLD { + 4 + 4 * size + ((size + 7) / 8) + } else { + 4 + 8 * size + ((size + 7) / 8) + } + } else { + out.write_u32::(SERIAL_COOKIE_NO_RUNCONTAINER)?; + out.write_u32::(containers.len().try_into().unwrap())?; + 4 + 4 + 4 * size + 4 * size + }; + for (&key, container) in keys.iter().zip(&containers) { + // descriptive header + let key: u32 = key.into(); + let count: u32 = container.popcount() - 1; + out.write_u32::((count << 16) | key)?; + } + if !has_run || size >= NO_OFFSET_THRESHOLD { + // offset header + let mut starting_offset = start_offset; + for container in &containers { + out.write_u32::(starting_offset)?; + starting_offset += match container { + Container::Bits(_) => 8192u32, + Container::Array(array) => u32::try_from(array.len()).unwrap() * 2, + Container::Run(runs) => 2 + u32::try_from(runs.len()).unwrap() * 4, + }; + } + } + for container in &containers { + match container { + Container::Bits(bits) => { + for chunk in bits.iter() { + out.write_u64::(*chunk)?; + } + } + Container::Array(array) => { + for value in array.iter() { + out.write_u16::(*value)?; + } + } + Container::Run(runs) => { + out.write_u16::((runs.len()).try_into().unwrap())?; + for (start, lenm1) in runs.iter().copied() { + out.write_u16::(start)?; + out.write_u16::(lenm1)?; + } + } + } + } + Ok(()) +} + pub(crate) fn get_function_type_for_search<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 15da5bf96b2ca..e70c5bfd734bf 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -242,6 +242,14 @@ function initSearch(rawSearchIndex) { * @type {Array} */ let searchIndex; + /** + * @type {Map} + */ + let searchIndexDeprecated; + /** + * @type {Map} + */ + let searchIndexEmptyDesc; /** * @type {Uint32Array} */ @@ -1326,7 +1334,6 @@ function initSearch(rawSearchIndex) { duplicates.add(obj.fullPath); obj.href = res[1]; - obj.desc = result.desc; out.push(obj); if (out.length >= MAX_RESULTS) { break; @@ -1353,12 +1360,6 @@ function initSearch(rawSearchIndex) { result.word = searchIndex[result.id].word; result_list.push(result); } - for (const result of result_list) { - result.desc = searchState.loadDesc(result.item); - } - for (const result of result_list) { - result.desc = await result.desc; - } result_list.sort((aaa, bbb) => { let a, b; @@ -1401,8 +1402,8 @@ function initSearch(rawSearchIndex) { } // sort deprecated items later - a = aaa.item.deprecated; - b = bbb.item.deprecated; + a = searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex); + b = searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex); if (a !== b) { return a - b; } @@ -1429,8 +1430,8 @@ function initSearch(rawSearchIndex) { } // sort by description (no description goes later) - a = (aaa.desc === ""); - b = (bbb.desc === ""); + a = searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex); + b = searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex); if (a !== b) { return a - b; } @@ -1453,7 +1454,16 @@ function initSearch(rawSearchIndex) { return 0; }); - return transformResults(result_list); + const transformed = transformResults(result_list); + for (const result of transformed) { + result.desc = searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ? + "" : + searchState.loadDesc(result); + } + for (const result of transformed) { + result.desc = await result.desc; + } + return transformed; } /** @@ -2079,7 +2089,7 @@ function initSearch(rawSearchIndex) { parent: item.parent, type: item.type, is_alias: true, - deprecated: item.deprecated, + bitIndex: item.bitIndex, implDisambiguator: item.implDisambiguator, }; } @@ -2712,9 +2722,11 @@ ${item.displayPath}${name}\ currentResults = results.query.userQuery; - const ret_others = await addTab(results.others, results.query, true); - const ret_in_args = await addTab(results.in_args, results.query, false); - const ret_returned = await addTab(results.returned, results.query, false); + const [ret_others, ret_in_args, ret_returned] = await Promise.all([ + addTab(results.others, results.query, true), + addTab(results.in_args, results.query, false), + addTab(results.returned, results.query, false), + ]); // Navigate to the relevant tab if the current tab is empty, like in case users search // for "-> String". If they had selected another tab previously, they have to click on @@ -3267,6 +3279,123 @@ ${item.displayPath}${name}\ return result; } } + class RoaringBitmap { + constructor(str) { + const strdecoded = atob(str); + const u8array = new Uint8Array(strdecoded.length); + for (let j = 0; j < strdecoded.length; ++j) { + u8array[j] = strdecoded.charCodeAt(j); + } + const has_runs = u8array[0] === 0x3b; + const size = has_runs ? + ((u8array[2] | (u8array[3] << 8)) + 1) : + ((u8array[4] | (u8array[5] << 8) | (u8array[6] << 16) | (u8array[7] << 24))); + let i = has_runs ? 4 : 8; + let is_run; + if (has_runs) { + const is_run_len = Math.floor((size + 7) / 8); + is_run = u8array.slice(i, i + is_run_len); + i += is_run_len; + } else { + is_run = new Uint8Array(); + } + this.keys = []; + this.cardinalities = []; + for (let j = 0; j < size; ++j) { + this.keys.push(u8array[i] | (u8array[i + 1] << 8)); + i += 2; + this.cardinalities.push((u8array[i] | (u8array[i + 1] << 8)) + 1); + i += 2; + } + this.containers = []; + let offsets = null; + if (!has_runs || this.keys.length >= 4) { + offsets = []; + for (let j = 0; j < size; ++j) { + offsets.push(u8array[i] | (u8array[i + 1] << 8) | (u8array[i + 2] << 16) | + (u8array[i + 3] << 24)); + i += 4; + } + } + for (let j = 0; j < size; ++j) { + if (offsets && offsets[j] !== i) { + console.log(this.containers); + throw new Error(`corrupt bitmap ${j}: ${i} / ${offsets[j]}`); + } + if (is_run[j >> 3] & (1 << (j & 0x7))) { + const runcount = (u8array[i] | (u8array[i + 1] << 8)); + i += 2; + this.containers.push(new RoaringBitmapRun( + runcount, + u8array.slice(i, i + (runcount * 4)), + )); + i += runcount * 4; + } else if (this.cardinalities[j] >= 4096) { + this.containers.push(new RoaringBitmapBits(u8array.slice(i, i + 8192))); + i += 8192; + } else { + const end = this.cardinalities[j] * 2; + this.containers.push(new RoaringBitmapArray( + this.cardinalities[j], + u8array.slice(i, i + end), + )); + i += end; + } + } + } + contains(keyvalue) { + const key = keyvalue >> 16; + const value = keyvalue & 0xFFFF; + for (let i = 0; i < this.keys.length; ++i) { + if (this.keys[i] === key) { + return this.containers[i].contains(value); + } + } + return false; + } + } + + class RoaringBitmapRun { + constructor(runcount, array) { + this.runcount = runcount; + this.array = array; + } + contains(value) { + const l = this.runcount * 4; + for (let i = 0; i < l; i += 4) { + const start = this.array[i] | (this.array[i + 1] << 8); + const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8); + if (value >= start && value <= (start + lenm1)) { + return true; + } + } + return false; + } + } + class RoaringBitmapArray { + constructor(cardinality, array) { + this.cardinality = cardinality; + this.array = array; + } + contains(value) { + const l = this.cardinality * 2; + for (let i = 0; i < l; i += 2) { + const start = this.array[i] | (this.array[i + 1] << 8); + if (value === start) { + return true; + } + } + return false; + } + } + class RoaringBitmapBits { + constructor(array) { + this.array = array; + } + contains(value) { + return !!(this.array[value >> 3] & (1 << (value & 7))); + } + } /** * Convert raw search index into in-memory search index. @@ -3275,6 +3404,8 @@ ${item.displayPath}${name}\ */ function buildIndex(rawSearchIndex) { searchIndex = []; + searchIndexDeprecated = new Map(); + searchIndexEmptyDesc = new Map(); const charA = "A".charCodeAt(0); let currentIndex = 0; let id = 0; @@ -3307,6 +3438,11 @@ ${item.displayPath}${name}\ }; const descShardList = [ descShard ]; + // Deprecated items and items with no description + searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); + searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); + let descIndex = 0; + // This object should have exactly the same set of fields as the "row" // object defined below. Your JavaScript runtime will thank you. // https://mathiasbynens.be/notes/shapes-ics @@ -3316,18 +3452,21 @@ ${item.displayPath}${name}\ name: crate, path: "", descShard, - descIndex: 0, + descIndex, parent: undefined, type: null, id, word: crate, normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""), - deprecated: null, + bitIndex: 0, implDisambiguator: null, }; id += 1; searchIndex.push(crateRow); currentIndex += 1; + if (!searchIndexEmptyDesc.get(crate).contains(0)) { + descIndex += 1; + } // a String of one character item type codes const itemTypes = crateCorpus.t; @@ -3341,9 +3480,7 @@ ${item.displayPath}${name}\ const itemPaths = new Map(crateCorpus.q); // an array of (Number) the parent path index + 1 to `paths`, or 0 if none const itemParentIdxs = crateCorpus.i; - // an array of (Number) indices for the deprecated items - const deprecatedItems = new Set(crateCorpus.c); - // an array of (Number) indices for the deprecated items + // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); // an array of [(Number) item type, // (String) name] @@ -3388,9 +3525,10 @@ ${item.displayPath}${name}\ // faster analysis operations lastPath = ""; len = itemTypes.length; - let descIndex = 1; for (let i = 0; i < len; ++i) { - if (descIndex >= descShard.len) { + const bitIndex = i + 1; + if (descIndex >= descShard.len && + !searchIndexEmptyDesc.get(crate).contains(bitIndex)) { descShard = { crate, shard: descShard.shard + 1, @@ -3439,13 +3577,15 @@ ${item.displayPath}${name}\ id, word, normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""), - deprecated: deprecatedItems.has(i), + bitIndex, implDisambiguator: implDisambiguator.has(i) ? implDisambiguator.get(i) : null, }; id += 1; searchIndex.push(row); lastPath = row.path; - descIndex += 1; + if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) { + descIndex += 1; + } } if (aliases) { diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 1af2f44c230d6..43a22f358c31f 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -559,8 +559,3 @@ process.on("beforeExit", () => { console.log("process did not complete"); process.exit(1); }); - -/*process.on("uncaughtException", (err) => { - console.log(`Uncaught Exception: ${err.message}`); - process.exit(1); -});*/ From c65f7d8ff181217e96662ec0ca4e5e6d9507d3dc Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 22 Mar 2024 17:00:38 -0700 Subject: [PATCH 06/12] rustdoc-search: address nits --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/search_index.rs | 301 +++--------------- .../html/render/search_index/encode.rs | 245 ++++++++++++++ src/librustdoc/html/static/js/main.js | 4 + src/librustdoc/html/static/js/search.js | 10 +- 5 files changed, 297 insertions(+), 265 deletions(-) create mode 100644 src/librustdoc/html/render/search_index/encode.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c1a7593c26f08..0c92dbd90f180 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -192,7 +192,7 @@ impl RenderTypeId { RenderTypeId::Index(idx) => (*idx).try_into().unwrap(), _ => panic!("must convert render types to indexes before serializing"), }; - search_index::write_vlqhex_to_string(id, string); + search_index::encode::write_vlqhex_to_string(id, string); } } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 2ec22df0b434f..60a3ada3b7c76 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1,7 +1,8 @@ +pub(crate) mod encode; + use std::collections::hash_map::Entry; use std::collections::{BTreeMap, VecDeque}; -use base64::prelude::*; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; @@ -18,12 +19,33 @@ use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; +use encode::{bitmap_to_string, write_vlqhex_to_string}; + /// The serialized search description sharded version /// /// The `index` is a JSON-encoded list of names and other information. /// /// The desc has newlined descriptions, split up by size into 128KiB shards. /// For example, `(4, "foo\nbar\nbaz\nquux")`. +/// +/// There is no single, optimal size for these shards, because it depends on +/// configuration values that we can't predict or control, such as the version +/// of HTTP used (HTTP/1.1 would work better with larger files, while HTTP/2 +/// and 3 are more agnostic), transport compression (gzip, zstd, etc), whether +/// the search query is going to produce a large number of results or a small +/// number, the bandwidth delay product of the network... +/// +/// Gzipping some standard library descriptions to guess what transport +/// compression will do, the compressed file sizes can be as small as 4.9KiB +/// or as large as 18KiB (ignoring the final 1.9KiB shard of leftovers). +/// A "reasonable" range for files is for them to be bigger than 1KiB, +/// since that's about the amount of data that can be transferred in a +/// single TCP packet, and 64KiB, the maximum amount of data that +/// TCP can transfer in a single round trip without extensions. +/// +/// [1]: https://en.wikipedia.org/wiki/Maximum_transmission_unit#MTUs_for_common_media +/// [2]: https://en.wikipedia.org/wiki/Sliding_window_protocol#Basic_concept +/// [3]: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/description-tcp-features pub(crate) struct SerializedSearchIndex { pub(crate) index: String, pub(crate) desc: Vec<(usize, String)>, @@ -342,9 +364,9 @@ pub(crate) fn build_index<'tcx>( associated_item_disambiguators: &'a Vec<(usize, String)>, // A list of shard lengths encoded as vlqhex. See the comment in write_vlqhex_to_string // for information on the format. - descindex: String, + desc_index: String, // A list of items with no description. This is eventually turned into a bitmap. - emptydesc: Vec, + empty_desc: Vec, } struct Paths { @@ -476,19 +498,11 @@ pub(crate) fn build_index<'tcx>( crate_data.serialize_field("q", &full_paths)?; crate_data.serialize_field("i", &parents)?; crate_data.serialize_field("f", &functions)?; - crate_data.serialize_field("D", &self.descindex)?; + crate_data.serialize_field("D", &self.desc_index)?; crate_data.serialize_field("p", &paths)?; crate_data.serialize_field("b", &self.associated_item_disambiguators)?; - let mut buf = Vec::new(); - let mut strbuf = String::new(); - write_bitmap_to_bytes(&deprecated, &mut buf).unwrap(); - BASE64_STANDARD.encode_string(&buf, &mut strbuf); - crate_data.serialize_field("c", &strbuf)?; - strbuf.clear(); - buf.clear(); - write_bitmap_to_bytes(&self.emptydesc, &mut buf).unwrap(); - BASE64_STANDARD.encode_string(&buf, &mut strbuf); - crate_data.serialize_field("e", &strbuf)?; + crate_data.serialize_field("c", &bitmap_to_string(&deprecated))?; + crate_data.serialize_field("e", &bitmap_to_string(&self.empty_desc))?; if has_aliases { crate_data.serialize_field("a", &self.aliases)?; } @@ -496,16 +510,16 @@ pub(crate) fn build_index<'tcx>( } } - let (emptydesc, desc) = { - let mut emptydesc = Vec::new(); + let (empty_desc, desc) = { + let mut empty_desc = Vec::new(); let mut result = Vec::new(); let mut set = String::new(); let mut len: usize = 0; - let mut itemindex: u32 = 0; + let mut item_index: u32 = 0; for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { if desc == "" { - emptydesc.push(itemindex); - itemindex += 1; + empty_desc.push(item_index); + item_index += 1; continue; } if set.len() >= DESC_INDEX_SHARD_LEN { @@ -516,23 +530,23 @@ pub(crate) fn build_index<'tcx>( } set.push_str(&desc); len += 1; - itemindex += 1; + item_index += 1; } result.push((len, std::mem::replace(&mut set, String::new()))); - (emptydesc, result) + (empty_desc, result) }; - let descindex = { - let mut descindex = String::with_capacity(desc.len() * 4); + let desc_index = { + let mut desc_index = String::with_capacity(desc.len() * 4); for &(len, _) in desc.iter() { - write_vlqhex_to_string(len.try_into().unwrap(), &mut descindex); + write_vlqhex_to_string(len.try_into().unwrap(), &mut desc_index); } - descindex + desc_index }; assert_eq!( crate_items.len() + 1, - desc.iter().map(|(len, _)| *len).sum::() + emptydesc.len() + desc.iter().map(|(len, _)| *len).sum::() + empty_desc.len() ); // The index, which is actually used to search, is JSON @@ -546,8 +560,8 @@ pub(crate) fn build_index<'tcx>( paths: crate_paths, aliases: &aliases, associated_item_disambiguators: &associated_item_disambiguators, - descindex, - emptydesc, + desc_index, + empty_desc, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. @@ -559,237 +573,6 @@ pub(crate) fn build_index<'tcx>( SerializedSearchIndex { index, desc } } -pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { - let (sign, magnitude): (bool, u32) = - if n >= 0 { (false, n.try_into().unwrap()) } else { (true, (-n).try_into().unwrap()) }; - // zig-zag encoding - let value: u32 = (magnitude << 1) | (if sign { 1 } else { 0 }); - // Self-terminating hex use capital letters for everything but the - // least significant digit, which is lowercase. For example, decimal 17 - // would be `` Aa `` if zig-zag encoding weren't used. - // - // Zig-zag encoding, however, stores the sign bit as the last bit. - // This means, in the last hexit, 1 is actually `c`, -1 is `b` - // (`a` is the imaginary -0), and, because all the bits are shifted - // by one, `` A` `` is actually 8 and `` Aa `` is -8. - // - // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html - // describes the encoding in more detail. - let mut shift: u32 = 28; - let mut mask: u32 = 0xF0_00_00_00; - // first skip leading zeroes - while shift < 32 { - let hexit = (value & mask) >> shift; - if hexit != 0 || shift == 0 { - break; - } - shift = shift.wrapping_sub(4); - mask = mask >> 4; - } - // now write the rest - while shift < 32 { - let hexit = (value & mask) >> shift; - let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); - string.push(hex); - shift = shift.wrapping_sub(4); - mask = mask >> 4; - } -} - -// checked against roaring-rs in -// https://gitlab.com/notriddle/roaring-test -pub fn write_bitmap_to_bytes(domain: &[u32], mut out: impl std::io::Write) -> std::io::Result<()> { - // https://arxiv.org/pdf/1603.06549.pdf - let mut keys = Vec::::new(); - let mut containers = Vec::::new(); - enum Container { - /// number of ones, bits - Bits(Box<[u64; 1024]>), - /// list of entries - Array(Vec), - /// list of (start, len-1) - Run(Vec<(u16, u16)>), - } - impl Container { - fn popcount(&self) -> u32 { - match self { - Container::Bits(bits) => bits.iter().copied().map(|x| x.count_ones()).sum(), - Container::Array(array) => { - array.len().try_into().expect("array can't be bigger than 2**32") - } - Container::Run(runs) => { - runs.iter().copied().map(|(_, lenm1)| u32::from(lenm1) + 1).sum() - } - } - } - fn push(&mut self, value: u16) { - match self { - Container::Bits(bits) => bits[value as usize >> 6] |= 1 << (value & 0x3F), - Container::Array(array) => { - array.push(value); - if array.len() >= 4096 { - let array = std::mem::replace(array, Vec::new()); - *self = Container::Bits(Box::new([0; 1024])); - for value in array { - self.push(value); - } - } - } - Container::Run(runs) => { - if let Some(r) = runs.last_mut() - && r.0 + r.1 + 1 == value - { - r.1 += 1; - } else { - runs.push((value, 0)); - } - } - } - } - fn try_make_run(&mut self) -> bool { - match self { - Container::Bits(bits) => { - let mut r: u64 = 0; - for (i, chunk) in bits.iter().copied().enumerate() { - let next_chunk = - i.checked_add(1).and_then(|i| bits.get(i)).copied().unwrap_or(0); - r += !chunk & u64::from((chunk << 1).count_ones()); - r += !next_chunk & u64::from((chunk >> 63).count_ones()); - } - if (2 + 4 * r) < 8192 { - let bits = std::mem::replace(bits, Box::new([0; 1024])); - *self = Container::Run(Vec::new()); - for (i, bits) in bits.iter().copied().enumerate() { - if bits == 0 { - continue; - } - for j in 0..64 { - let value = (u16::try_from(i).unwrap() << 6) | j; - if bits & (1 << j) != 0 { - self.push(value); - } - } - } - true - } else { - false - } - } - Container::Array(array) if array.len() <= 5 => false, - Container::Array(array) => { - let mut r = 0; - let mut prev = None; - for value in array.iter().copied() { - if value.checked_sub(1) != prev { - r += 1; - } - prev = Some(value); - } - if 2 + 4 * r < 2 * array.len() + 2 { - let array = std::mem::replace(array, Vec::new()); - *self = Container::Run(Vec::new()); - for value in array { - self.push(value); - } - true - } else { - false - } - } - Container::Run(_) => true, - } - } - } - let mut key: u16; - let mut domain_iter = domain.into_iter().copied().peekable(); - let mut has_run = false; - while let Some(entry) = domain_iter.next() { - key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); - let value: u16 = (entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit"); - let mut container = Container::Array(vec![value]); - while let Some(entry) = domain_iter.peek().copied() { - let entry_key: u16 = - (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); - if entry_key != key { - break; - } - domain_iter.next().expect("peeking just succeeded"); - container - .push((entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit")); - } - keys.push(key); - has_run = container.try_make_run() || has_run; - containers.push(container); - } - // https://github.com/RoaringBitmap/RoaringFormatSpec - use byteorder::{WriteBytesExt, LE}; - const SERIAL_COOKIE_NO_RUNCONTAINER: u32 = 12346; - const SERIAL_COOKIE: u32 = 12347; - const NO_OFFSET_THRESHOLD: u32 = 4; - let size: u32 = containers.len().try_into().unwrap(); - let start_offset = if has_run { - out.write_u32::(SERIAL_COOKIE | ((size - 1) << 16))?; - for set in containers.chunks(8) { - let mut b = 0; - for (i, container) in set.iter().enumerate() { - if matches!(container, &Container::Run(..)) { - b |= 1 << i; - } - } - out.write_u8(b)?; - } - if size < NO_OFFSET_THRESHOLD { - 4 + 4 * size + ((size + 7) / 8) - } else { - 4 + 8 * size + ((size + 7) / 8) - } - } else { - out.write_u32::(SERIAL_COOKIE_NO_RUNCONTAINER)?; - out.write_u32::(containers.len().try_into().unwrap())?; - 4 + 4 + 4 * size + 4 * size - }; - for (&key, container) in keys.iter().zip(&containers) { - // descriptive header - let key: u32 = key.into(); - let count: u32 = container.popcount() - 1; - out.write_u32::((count << 16) | key)?; - } - if !has_run || size >= NO_OFFSET_THRESHOLD { - // offset header - let mut starting_offset = start_offset; - for container in &containers { - out.write_u32::(starting_offset)?; - starting_offset += match container { - Container::Bits(_) => 8192u32, - Container::Array(array) => u32::try_from(array.len()).unwrap() * 2, - Container::Run(runs) => 2 + u32::try_from(runs.len()).unwrap() * 4, - }; - } - } - for container in &containers { - match container { - Container::Bits(bits) => { - for chunk in bits.iter() { - out.write_u64::(*chunk)?; - } - } - Container::Array(array) => { - for value in array.iter() { - out.write_u16::(*value)?; - } - } - Container::Run(runs) => { - out.write_u16::((runs.len()).try_into().unwrap())?; - for (start, lenm1) in runs.iter().copied() { - out.write_u16::(start)?; - out.write_u16::(lenm1)?; - } - } - } - } - Ok(()) -} - pub(crate) fn get_function_type_for_search<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs new file mode 100644 index 0000000000000..af5eccd5bedc6 --- /dev/null +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -0,0 +1,245 @@ +use base64::prelude::*; + +pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { + let (sign, magnitude): (bool, u32) = + if n >= 0 { (false, n.try_into().unwrap()) } else { (true, (-n).try_into().unwrap()) }; + // zig-zag encoding + let value: u32 = (magnitude << 1) | (if sign { 1 } else { 0 }); + // Self-terminating hex use capital letters for everything but the + // least significant digit, which is lowercase. For example, decimal 17 + // would be `` Aa `` if zig-zag encoding weren't used. + // + // Zig-zag encoding, however, stores the sign bit as the last bit. + // This means, in the last hexit, 1 is actually `c`, -1 is `b` + // (`a` is the imaginary -0), and, because all the bits are shifted + // by one, `` A` `` is actually 8 and `` Aa `` is -8. + // + // https://rust-lang.github.io/rustc-dev-guide/rustdoc-internals/search.html + // describes the encoding in more detail. + let mut shift: u32 = 28; + let mut mask: u32 = 0xF0_00_00_00; + // first skip leading zeroes + while shift < 32 { + let hexit = (value & mask) >> shift; + if hexit != 0 || shift == 0 { + break; + } + shift = shift.wrapping_sub(4); + mask = mask >> 4; + } + // now write the rest + while shift < 32 { + let hexit = (value & mask) >> shift; + let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); + string.push(hex); + shift = shift.wrapping_sub(4); + mask = mask >> 4; + } +} + +// Used during bitmap encoding +enum Container { + /// number of ones, bits + Bits(Box<[u64; 1024]>), + /// list of entries + Array(Vec), + /// list of (start, len-1) + Run(Vec<(u16, u16)>), +} +impl Container { + fn popcount(&self) -> u32 { + match self { + Container::Bits(bits) => bits.iter().copied().map(|x| x.count_ones()).sum(), + Container::Array(array) => { + array.len().try_into().expect("array can't be bigger than 2**32") + } + Container::Run(runs) => { + runs.iter().copied().map(|(_, lenm1)| u32::from(lenm1) + 1).sum() + } + } + } + fn push(&mut self, value: u16) { + match self { + Container::Bits(bits) => bits[value as usize >> 6] |= 1 << (value & 0x3F), + Container::Array(array) => { + array.push(value); + if array.len() >= 4096 { + let array = std::mem::replace(array, Vec::new()); + *self = Container::Bits(Box::new([0; 1024])); + for value in array { + self.push(value); + } + } + } + Container::Run(runs) => { + if let Some(r) = runs.last_mut() + && r.0 + r.1 + 1 == value + { + r.1 += 1; + } else { + runs.push((value, 0)); + } + } + } + } + fn try_make_run(&mut self) -> bool { + match self { + Container::Bits(bits) => { + let mut r: u64 = 0; + for (i, chunk) in bits.iter().copied().enumerate() { + let next_chunk = + i.checked_add(1).and_then(|i| bits.get(i)).copied().unwrap_or(0); + r += !chunk & u64::from((chunk << 1).count_ones()); + r += !next_chunk & u64::from((chunk >> 63).count_ones()); + } + if (2 + 4 * r) < 8192 { + let bits = std::mem::replace(bits, Box::new([0; 1024])); + *self = Container::Run(Vec::new()); + for (i, bits) in bits.iter().copied().enumerate() { + if bits == 0 { + continue; + } + for j in 0..64 { + let value = (u16::try_from(i).unwrap() << 6) | j; + if bits & (1 << j) != 0 { + self.push(value); + } + } + } + true + } else { + false + } + } + Container::Array(array) if array.len() <= 5 => false, + Container::Array(array) => { + let mut r = 0; + let mut prev = None; + for value in array.iter().copied() { + if value.checked_sub(1) != prev { + r += 1; + } + prev = Some(value); + } + if 2 + 4 * r < 2 * array.len() + 2 { + let array = std::mem::replace(array, Vec::new()); + *self = Container::Run(Vec::new()); + for value in array { + self.push(value); + } + true + } else { + false + } + } + Container::Run(_) => true, + } + } +} + +// checked against roaring-rs in +// https://gitlab.com/notriddle/roaring-test +pub(crate) fn write_bitmap_to_bytes( + domain: &[u32], + mut out: impl std::io::Write, +) -> std::io::Result<()> { + // https://arxiv.org/pdf/1603.06549.pdf + let mut keys = Vec::::new(); + let mut containers = Vec::::new(); + let mut key: u16; + let mut domain_iter = domain.into_iter().copied().peekable(); + let mut has_run = false; + while let Some(entry) = domain_iter.next() { + key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); + let value: u16 = (entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit"); + let mut container = Container::Array(vec![value]); + while let Some(entry) = domain_iter.peek().copied() { + let entry_key: u16 = + (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); + if entry_key != key { + break; + } + domain_iter.next().expect("peeking just succeeded"); + container + .push((entry & 0x00_00_FF_FF).try_into().expect("AND 16 bits, so it should fit")); + } + keys.push(key); + has_run = container.try_make_run() || has_run; + containers.push(container); + } + // https://github.com/RoaringBitmap/RoaringFormatSpec + use byteorder::{WriteBytesExt, LE}; + const SERIAL_COOKIE_NO_RUNCONTAINER: u32 = 12346; + const SERIAL_COOKIE: u32 = 12347; + const NO_OFFSET_THRESHOLD: u32 = 4; + let size: u32 = containers.len().try_into().unwrap(); + let start_offset = if has_run { + out.write_u32::(SERIAL_COOKIE | ((size - 1) << 16))?; + for set in containers.chunks(8) { + let mut b = 0; + for (i, container) in set.iter().enumerate() { + if matches!(container, &Container::Run(..)) { + b |= 1 << i; + } + } + out.write_u8(b)?; + } + if size < NO_OFFSET_THRESHOLD { + 4 + 4 * size + ((size + 7) / 8) + } else { + 4 + 8 * size + ((size + 7) / 8) + } + } else { + out.write_u32::(SERIAL_COOKIE_NO_RUNCONTAINER)?; + out.write_u32::(containers.len().try_into().unwrap())?; + 4 + 4 + 4 * size + 4 * size + }; + for (&key, container) in keys.iter().zip(&containers) { + // descriptive header + let key: u32 = key.into(); + let count: u32 = container.popcount() - 1; + out.write_u32::((count << 16) | key)?; + } + if !has_run || size >= NO_OFFSET_THRESHOLD { + // offset header + let mut starting_offset = start_offset; + for container in &containers { + out.write_u32::(starting_offset)?; + starting_offset += match container { + Container::Bits(_) => 8192u32, + Container::Array(array) => u32::try_from(array.len()).unwrap() * 2, + Container::Run(runs) => 2 + u32::try_from(runs.len()).unwrap() * 4, + }; + } + } + for container in &containers { + match container { + Container::Bits(bits) => { + for chunk in bits.iter() { + out.write_u64::(*chunk)?; + } + } + Container::Array(array) => { + for value in array.iter() { + out.write_u16::(*value)?; + } + } + Container::Run(runs) => { + out.write_u16::((runs.len()).try_into().unwrap())?; + for (start, lenm1) in runs.iter().copied() { + out.write_u16::(start)?; + out.write_u16::(lenm1)?; + } + } + } + } + Ok(()) +} + +pub(crate) fn bitmap_to_string(domain: &[u32]) -> String { + let mut buf = Vec::new(); + let mut strbuf = String::new(); + write_bitmap_to_bytes(&domain, &mut buf).unwrap(); + BASE64_STANDARD.encode_string(&buf, &mut strbuf); + strbuf +} diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index eff3dc27911bf..940b62be0c94d 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -333,6 +333,10 @@ function preLoadCss(cssUrl) { loadDesc: async function({descShard, descIndex}) { if (descShard.promise === null) { descShard.promise = new Promise((resolve, reject) => { + // The `resolve` callback is stored in the `descShard` + // object, which is itself stored in `this.descShards` map. + // It is called in `loadedDescShard` by the + // search.desc script. descShard.resolve = resolve; const ds = descShard; const fname = `${ds.crate}-desc-${ds.shard}-`; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index e70c5bfd734bf..3daf1ad22ded3 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1455,13 +1455,13 @@ function initSearch(rawSearchIndex) { }); const transformed = transformResults(result_list); - for (const result of transformed) { - result.desc = searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ? + const descs = await Promise.all(transformed.map(result => { + return searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ? "" : searchState.loadDesc(result); - } - for (const result of transformed) { - result.desc = await result.desc; + })); + for (const [i, result] of transformed.entries()) { + result.desc = descs[i]; } return transformed; } From 59120d0ef54fdb860cb88a9169eb3ff71d2799b3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 1 Apr 2024 21:11:22 +0200 Subject: [PATCH 07/12] Update to new browser-ui-test version --- .../x86_64-gnu-tools/browser-ui-test.version | 2 +- tests/rustdoc-gui/anchors.goml | 2 +- tests/rustdoc-gui/code-color.goml | 2 +- tests/rustdoc-gui/codeblock-tooltip.goml | 2 +- tests/rustdoc-gui/cursor.goml | 2 +- .../docblock-code-block-line-number.goml | 2 +- tests/rustdoc-gui/docblock-table.goml | 2 +- tests/rustdoc-gui/escape-key.goml | 2 +- tests/rustdoc-gui/globals.goml | 2 +- tests/rustdoc-gui/go-to-collapsed-elem.goml | 4 +- tests/rustdoc-gui/headers-color.goml | 2 +- tests/rustdoc-gui/headings-anchor.goml | 8 +- tests/rustdoc-gui/headings.goml | 10 +- tests/rustdoc-gui/help-page.goml | 8 +- tests/rustdoc-gui/highlight-colors.goml | 4 +- tests/rustdoc-gui/item-decl-colors.goml | 4 +- .../item-decl-comment-highlighting.goml | 4 +- tests/rustdoc-gui/item-info-alignment.goml | 4 +- tests/rustdoc-gui/item-info.goml | 4 +- tests/rustdoc-gui/jump-to-def-background.goml | 17 +- tests/rustdoc-gui/label-next-to-symbol.goml | 12 +- tests/rustdoc-gui/links-color.goml | 4 +- tests/rustdoc-gui/notable-trait.goml | 20 +- tests/rustdoc-gui/pocket-menu.goml | 2 +- tests/rustdoc-gui/run-on-hover.goml | 2 +- tests/rustdoc-gui/rust-logo.goml | 2 +- tests/rustdoc-gui/scrape-examples-color.goml | 6 +- tests/rustdoc-gui/scrape-examples-toggle.goml | 2 +- tests/rustdoc-gui/search-corrections.goml | 10 +- tests/rustdoc-gui/search-error.goml | 2 +- tests/rustdoc-gui/search-filter.goml | 2 +- tests/rustdoc-gui/search-form-elements.goml | 4 +- tests/rustdoc-gui/search-keyboard.goml | 2 +- tests/rustdoc-gui/search-no-result.goml | 2 +- tests/rustdoc-gui/search-reexport.goml | 4 +- tests/rustdoc-gui/search-result-color.goml | 246 +++++++++--------- tests/rustdoc-gui/search-result-display.goml | 4 +- .../search-result-impl-disambiguation.goml | 4 +- tests/rustdoc-gui/search-result-keyword.goml | 2 +- .../search-tab-change-title-fn-sig.goml | 10 +- tests/rustdoc-gui/search-tab.goml | 12 +- ...setting-auto-hide-content-large-items.goml | 2 +- .../setting-auto-hide-item-methods-docs.goml | 2 +- ...tting-auto-hide-trait-implementations.goml | 2 +- .../setting-go-to-only-result.goml | 4 +- tests/rustdoc-gui/settings.goml | 2 +- tests/rustdoc-gui/sidebar-links-color.goml | 4 +- tests/rustdoc-gui/sidebar-mobile.goml | 2 +- .../sidebar-source-code-display.goml | 4 +- tests/rustdoc-gui/sidebar-source-code.goml | 2 +- tests/rustdoc-gui/sidebar.goml | 2 +- tests/rustdoc-gui/source-code-page.goml | 6 +- tests/rustdoc-gui/stab-badge.goml | 2 +- tests/rustdoc-gui/target.goml | 2 +- tests/rustdoc-gui/toggle-docs.goml | 2 +- .../rustdoc-gui/type-declation-overflow.goml | 8 +- tests/rustdoc-gui/unsafe-fn.goml | 17 +- tests/rustdoc-gui/warning-block.goml | 2 +- tests/rustdoc-gui/where-whitespace.goml | 10 +- 59 files changed, 267 insertions(+), 249 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index a2b63962ba11e..07feb8234926c 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.16.11 \ No newline at end of file +0.17.0 \ No newline at end of file diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml index 72e0bcd77e08c..3239e54a866b5 100644 --- a/tests/rustdoc-gui/anchors.goml +++ b/tests/rustdoc-gui/anchors.goml @@ -2,7 +2,7 @@ define-function: ( "check-colors", - (theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color), + [theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color], block { go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" // This is needed to ensure that the text color is computed. diff --git a/tests/rustdoc-gui/code-color.goml b/tests/rustdoc-gui/code-color.goml index 92bdfb25b001c..e17af5e7f1fa4 100644 --- a/tests/rustdoc-gui/code-color.goml +++ b/tests/rustdoc-gui/code-color.goml @@ -8,7 +8,7 @@ show-text: true define-function: ( "check-colors", - (theme, doc_code_color, doc_inline_code_color), + [theme, doc_code_color, doc_inline_code_color], block { // Set the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml index 7be5e39ba4727..19e3927f64293 100644 --- a/tests/rustdoc-gui/codeblock-tooltip.goml +++ b/tests/rustdoc-gui/codeblock-tooltip.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-colors", - (theme, background, color, border), + [theme, background, color, border], block { // Setting the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} diff --git a/tests/rustdoc-gui/cursor.goml b/tests/rustdoc-gui/cursor.goml index 27c955f5a13ac..9412987fc3238 100644 --- a/tests/rustdoc-gui/cursor.goml +++ b/tests/rustdoc-gui/cursor.goml @@ -8,7 +8,7 @@ assert-css: ("#toggle-all-docs", {"cursor": "pointer"}) assert-css: ("#copy-path", {"cursor": "pointer"}) // the search tabs -write: (".search-input", "Foo") +write-into: (".search-input", "Foo") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index a50449e17010f..cb7bdaab4c8db 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -10,7 +10,7 @@ assert-false: "pre.example-line-numbers" // Let's now check some CSS properties... define-function: ( "check-colors", - (theme, color), + [theme, color], block { // We now set the setting to show the line numbers on code examples. set-local-storage: { diff --git a/tests/rustdoc-gui/docblock-table.goml b/tests/rustdoc-gui/docblock-table.goml index 678b302f22e3b..db6d065a4b338 100644 --- a/tests/rustdoc-gui/docblock-table.goml +++ b/tests/rustdoc-gui/docblock-table.goml @@ -6,7 +6,7 @@ compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock tab define-function: ( "check-colors", - (theme, border_color, zebra_stripe_color), + [theme, border_color, zebra_stripe_color], block { set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} reload: diff --git a/tests/rustdoc-gui/escape-key.goml b/tests/rustdoc-gui/escape-key.goml index 3ea20fd118e6a..ff8557b9b81ca 100644 --- a/tests/rustdoc-gui/escape-key.goml +++ b/tests/rustdoc-gui/escape-key.goml @@ -2,7 +2,7 @@ // current content displayed. go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // First, we check that the search results are hidden when the Escape key is pressed. -write: (".search-input", "test") +write-into: (".search-input", "test") // To be SURE that the search will be run. press-key: 'Enter' wait-for: "#search h1" // The search element is empty before the first search diff --git a/tests/rustdoc-gui/globals.goml b/tests/rustdoc-gui/globals.goml index c01c8bb101913..f8c495ec18a69 100644 --- a/tests/rustdoc-gui/globals.goml +++ b/tests/rustdoc-gui/globals.goml @@ -10,7 +10,7 @@ assert-window-property: {"srcIndex": null} // Form input go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "Foo") +write-into: (".search-input", "Foo") press-key: 'Enter' wait-for: "#search-tabs" assert-window-property-false: {"searchIndex": null} diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml index 80e9791775e47..e56e7ba08cd81 100644 --- a/tests/rustdoc-gui/go-to-collapsed-elem.goml +++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml @@ -9,14 +9,14 @@ set-property: ("#implementations-list .implementors-toggle", {"open": "false"}) click: "//*[@class='sidebar']//a[@href='#method.must_use']" assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) -define-function: ("collapsed-from-search", (), block { +define-function: ("collapsed-from-search", [], block { // Now we do the same through search result. // First we reload the page without the anchor in the URL. go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // Then we collapse the section again... set-property: ("#implementations-list .implementors-toggle", {"open": "false"}) // Then we run the search. - write: (".search-input", "foo::must_use") + write-into: (".search-input", "foo::must_use") wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index 80d11c9c849cf..2a181c0669fe9 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -2,7 +2,7 @@ define-function: ( "check-colors", - (theme, color, code_header_color, focus_background_color, headings_color), + [theme, color, code_header_color, focus_background_color, headings_color], block { go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // This is needed so that the text color is computed. diff --git a/tests/rustdoc-gui/headings-anchor.goml b/tests/rustdoc-gui/headings-anchor.goml index f568caa3b07fe..9d52c2ac4b5c8 100644 --- a/tests/rustdoc-gui/headings-anchor.goml +++ b/tests/rustdoc-gui/headings-anchor.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-heading-anchor", - (heading_id), + [heading_id], block { // The anchor should not be displayed by default. assert-css: ("#" + |heading_id| + " .doc-anchor", { "display": "none" }) @@ -27,6 +27,6 @@ move-cursor-to: "#top-doc-prose-title" // to prevent it from overlapping with the `[-]` element. assert-css: ("#top-doc-prose-title:hover .doc-anchor", { "display": "none" }) -call-function: ("check-heading-anchor", ("top-doc-prose-sub-heading")) -call-function: ("check-heading-anchor", ("top-doc-prose-sub-sub-heading")) -call-function: ("check-heading-anchor", ("you-know-the-drill")) +call-function: ("check-heading-anchor", {"heading_id": "top-doc-prose-sub-heading"}) +call-function: ("check-heading-anchor", {"heading_id": "top-doc-prose-sub-sub-heading"}) +call-function: ("check-heading-anchor", {"heading_id": "you-know-the-drill"}) diff --git a/tests/rustdoc-gui/headings.goml b/tests/rustdoc-gui/headings.goml index 102b699b1dd1d..cdc61e36be200 100644 --- a/tests/rustdoc-gui/headings.goml +++ b/tests/rustdoc-gui/headings.goml @@ -156,7 +156,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" define-function: ( "check-colors", - (theme, heading_color, small_heading_color, heading_border_color), + [theme, heading_color, small_heading_color, heading_border_color], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: @@ -220,7 +220,7 @@ call-function: ( define-function: ( "check-since-color", - (theme), + [theme], block { set-local-storage: {"rustdoc-theme": |theme|} reload: @@ -229,6 +229,6 @@ define-function: ( ) go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" -call-function: ("check-since-color", ("ayu")) -call-function: ("check-since-color", ("dark")) -call-function: ("check-since-color", ("light")) +call-function: ("check-since-color", {"theme": "ayu"}) +call-function: ("check-since-color", {"theme": "dark"}) +call-function: ("check-since-color", {"theme": "light"}) diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml index 84c20355500ab..9a7247a737ba9 100644 --- a/tests/rustdoc-gui/help-page.goml +++ b/tests/rustdoc-gui/help-page.goml @@ -7,17 +7,17 @@ assert-css: ("#help dd", {"font-size": "16px"}) click: "#help-button > a" assert-css: ("#help", {"display": "block"}) compare-elements-property: (".sub", "#help", ["offsetWidth"]) -compare-elements-position: (".sub", "#help", ("x")) +compare-elements-position: (".sub", "#help", ["x"]) set-window-size: (500, 1000) // Try mobile next. assert-css: ("#help", {"display": "block"}) compare-elements-property: (".sub", "#help", ["offsetWidth"]) -compare-elements-position: (".sub", "#help", ("x")) +compare-elements-position: (".sub", "#help", ["x"]) // Checking the color of the elements of the help menu. show-text: true define-function: ( "check-colors", - (theme, color, background, box_shadow), + [theme, color, background, box_shadow], block { // Setting the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} @@ -60,7 +60,7 @@ assert-css: ("#help dd", {"font-size": "16px"}) click: "#help-button > a" assert-css: ("#help", {"display": "none"}) compare-elements-property-false: (".sub", "#help", ["offsetWidth"]) -compare-elements-position-false: (".sub", "#help", ("x")) +compare-elements-position-false: (".sub", "#help", ["x"]) // This test ensures that the "the rustdoc book" anchor link within the help popover works. go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" diff --git a/tests/rustdoc-gui/highlight-colors.goml b/tests/rustdoc-gui/highlight-colors.goml index d162674fa6976..48bef319d42f8 100644 --- a/tests/rustdoc-gui/highlight-colors.goml +++ b/tests/rustdoc-gui/highlight-colors.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-colors", - ( + [ theme, kw, kw2, @@ -20,7 +20,7 @@ define-function: ( question_mark, comment, doc_comment, - ), + ], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/item-decl-colors.goml b/tests/rustdoc-gui/item-decl-colors.goml index 7bbd20c4ee006..e68d206a51181 100644 --- a/tests/rustdoc-gui/item-decl-colors.goml +++ b/tests/rustdoc-gui/item-decl-colors.goml @@ -6,7 +6,7 @@ fail-on-request-error: false define-function: ( "check-colors", - ( + [ theme, attr_color, trait_color, @@ -16,7 +16,7 @@ define-function: ( constant_color, fn_color, assoc_type_color, - ), + ], block { go-to: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html" show-text: true diff --git a/tests/rustdoc-gui/item-decl-comment-highlighting.goml b/tests/rustdoc-gui/item-decl-comment-highlighting.goml index 60772693d6c5c..056b6a5b1e811 100644 --- a/tests/rustdoc-gui/item-decl-comment-highlighting.goml +++ b/tests/rustdoc-gui/item-decl-comment-highlighting.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-item-decl-comment", - (theme, url, comment_color), + [theme, url, comment_color], block { go-to: |url| set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} @@ -15,7 +15,7 @@ define-function: ( define-function: ( "check-items-for-theme", - (theme, comment_color), + [theme, comment_color], block { call-function: ("check-item-decl-comment", { "theme": |theme|, diff --git a/tests/rustdoc-gui/item-info-alignment.goml b/tests/rustdoc-gui/item-info-alignment.goml index 6fc365d1f1942..cd0624056b9a1 100644 --- a/tests/rustdoc-gui/item-info-alignment.goml +++ b/tests/rustdoc-gui/item-info-alignment.goml @@ -4,7 +4,7 @@ go-to: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html" // First, we try it in "desktop" mode. set-window-size: (1200, 870) -compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x")) +compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) // Next, we try it in "mobile" mode (max-width: 700px). set-window-size: (650, 650) -compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x")) +compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index b46d4255ee519..1eb46e832b70b 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -31,13 +31,13 @@ assert-count: ("#main-content > .item-info .stab", 2) compare-elements-position-false: ( "#main-content > .item-info .stab:nth-of-type(1)", "#main-content > .item-info .stab:nth-of-type(2)", - ("y"), + ["y"], ) // But they should have the same `x` position. compare-elements-position: ( "#main-content > .item-info .stab:nth-of-type(1)", "#main-content > .item-info .stab:nth-of-type(2)", - ("x"), + ["x"], ) // They are supposed to have the same height too. compare-elements-css: ( diff --git a/tests/rustdoc-gui/jump-to-def-background.goml b/tests/rustdoc-gui/jump-to-def-background.goml index fa7ed3586dd52..ae9c0c560cf30 100644 --- a/tests/rustdoc-gui/jump-to-def-background.goml +++ b/tests/rustdoc-gui/jump-to-def-background.goml @@ -3,7 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html" define-function: ( "check-background-color", - (theme, background_color), + [theme, background_color], block { // Set the theme. set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } @@ -17,6 +17,15 @@ define-function: ( }, ) -call-function: ("check-background-color", ("ayu", "#333")) -call-function: ("check-background-color", ("dark", "#333")) -call-function: ("check-background-color", ("light", "#eee")) +call-function: ("check-background-color", { + "theme": "ayu", + "background_color": "#333", +}) +call-function: ("check-background-color", { + "theme": "dark", + "background_color": "#333", +}) +call-function: ("check-background-color", { + "theme": "light", + "background_color": "#eee", +}) diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml index d23f9114d3616..9a7de60bf38e1 100644 --- a/tests/rustdoc-gui/label-next-to-symbol.goml +++ b/tests/rustdoc-gui/label-next-to-symbol.goml @@ -27,14 +27,14 @@ compare-elements-position-near: ( compare-elements-position: ( ".item-name .stab.deprecated", ".item-name .stab.portability", - ("y"), + ["y"], ) // Ensure no wrap compare-elements-position: ( "//*[@class='item-name']//a[text()='replaced_function']/..", "//*[@class='desc docblock-short'][text()='a thing with a label']", - ("y"), + ["y"], ) // Mobile view @@ -49,19 +49,19 @@ compare-elements-position-near: ( compare-elements-position: ( ".item-name .stab.deprecated", ".item-name .stab.portability", - ("y"), + ["y"], ) // Ensure wrap compare-elements-position-false: ( "//*[@class='item-name']//a[text()='replaced_function']/..", "//*[@class='desc docblock-short'][text()='a thing with a label']", - ("y"), + ["y"], ) compare-elements-position-false: ( ".item-name .stab.deprecated", "//*[@class='desc docblock-short'][text()='a thing with a label']", - ("y"), + ["y"], ) // Ensure it doesn't expand. @@ -72,5 +72,5 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/cfgs/index.html" compare-elements-position-false: ( "//*[@class='stab portability']/code[text()='appservice-api-c']", "//*[@class='stab portability']/code[text()='server']", - ("y"), + ["y"], ) diff --git a/tests/rustdoc-gui/links-color.goml b/tests/rustdoc-gui/links-color.goml index d88ebfb40d7a8..a1fb619a5d34c 100644 --- a/tests/rustdoc-gui/links-color.goml +++ b/tests/rustdoc-gui/links-color.goml @@ -6,8 +6,8 @@ show-text: true define-function: ( "check-colors", - (theme, mod, macro, struct, enum, trait, fn, type, union, keyword, - sidebar, sidebar_current, sidebar_current_background), + [theme, mod, macro, struct, enum, trait, fn, type, union, keyword, + sidebar, sidebar_current, sidebar_current_background], block { set-local-storage: { "rustdoc-theme": |theme|, diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index e10bb538f0780..0b1c6622596a1 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -7,13 +7,13 @@ set-window-size: (1100, 600) compare-elements-position: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("y"), + ["y"], ) // Checking they don't have the same x position. compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("x"), + ["x"], ) // The `i` should be *after* the type. assert-position: ( @@ -37,7 +37,7 @@ compare-elements-position-near: ( compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", "//*[@class='tooltip popover']", - ("x") + ["x"] ) click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" move-cursor-to: "//h1" @@ -48,7 +48,7 @@ set-window-size: (1055, 600) compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("y", "x"), + ["y", "x"], ) // Now both the `i` and the struct name should be on the next line. @@ -57,13 +57,13 @@ set-window-size: (980, 600) compare-elements-position: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("y"), + ["y"], ) // Checking they don't have the same x position. compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("x"), + ["x"], ) // The `i` should be *after* the type. assert-position: ( @@ -81,13 +81,13 @@ set-window-size: (650, 600) compare-elements-position: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("y"), + ["y"], ) // Checking they don't have the same x position. compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ("x"), + ["x"], ) // The `i` should be *after* the type. assert-position: ( @@ -109,7 +109,7 @@ compare-elements-position-near: ( compare-elements-position-false: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", "//*[@class='tooltip popover']", - ("x") + ["x"] ) assert-position: ( "//*[@class='tooltip popover']", @@ -122,7 +122,7 @@ assert-count: ("//*[@class='tooltip popover']", 0) // Now check the colors. define-function: ( "check-colors", - (theme, header_color, content_color, type_color, trait_color, link_color), + [theme, header_color, content_color, type_color, trait_color, link_color], block { go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html" // This is needed to ensure that the text color is computed. diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml index 404e574030591..b16150cd0d368 100644 --- a/tests/rustdoc-gui/pocket-menu.goml +++ b/tests/rustdoc-gui/pocket-menu.goml @@ -31,7 +31,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"}) define-function: ( "check-popover-colors", - (theme, border_color), + [theme, border_color], block { set-local-storage: { "rustdoc-theme": |theme|, diff --git a/tests/rustdoc-gui/run-on-hover.goml b/tests/rustdoc-gui/run-on-hover.goml index 1f87febcec6b6..19b15afbac3ca 100644 --- a/tests/rustdoc-gui/run-on-hover.goml +++ b/tests/rustdoc-gui/run-on-hover.goml @@ -7,7 +7,7 @@ show-text: true define-function: ( "check-run-button", - (theme, color, background, hover_color, hover_background), + [theme, color, background, hover_color, hover_background], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/rust-logo.goml b/tests/rustdoc-gui/rust-logo.goml index dcf3d6bab6382..a3b420e5eb92c 100644 --- a/tests/rustdoc-gui/rust-logo.goml +++ b/tests/rustdoc-gui/rust-logo.goml @@ -3,7 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/staged_api/index.html" define-function: ( "check-logo", - (theme, filter), + [theme, filter], block { // Going to the doc page. go-to: "file://" + |DOC_PATH| + "/staged_api/index.html" diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml index 0052d18dc560d..b1675a5f1fd7e 100644 --- a/tests/rustdoc-gui/scrape-examples-color.goml +++ b/tests/rustdoc-gui/scrape-examples-color.goml @@ -4,8 +4,8 @@ show-text: true define-function: ( "check-colors", - (theme, highlight, highlight_focus, help_border, help_color, help_hover_border, - help_hover_color), + [theme, highlight, highlight_focus, help_border, help_color, help_hover_border, + help_hover_color], block { set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", } reload: @@ -64,7 +64,7 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" define-function: ( "check-background", - (theme, background_color_start, background_color_end), + [theme, background_color_start, background_color_end], block { set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", } reload: diff --git a/tests/rustdoc-gui/scrape-examples-toggle.goml b/tests/rustdoc-gui/scrape-examples-toggle.goml index f742b3186e5b2..ea645d2892444 100644 --- a/tests/rustdoc-gui/scrape-examples-toggle.goml +++ b/tests/rustdoc-gui/scrape-examples-toggle.goml @@ -5,7 +5,7 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" show-text: true define-function: ( "check-color", - (theme, toggle_line_color, toggle_line_hover_color), + [theme, toggle_line_color, toggle_line_hover_color], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/search-corrections.goml b/tests/rustdoc-gui/search-corrections.goml index aeb3c9b31a3fd..b81b1f382a957 100644 --- a/tests/rustdoc-gui/search-corrections.goml +++ b/tests/rustdoc-gui/search-corrections.goml @@ -4,7 +4,7 @@ // First, try a search-by-name go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // Intentionally wrong spelling of "NotableStructWithLongName" -write: (".search-input", "NotableStructWithLongNamr") +write-into: (".search-input", "NotableStructWithLongNamr") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -41,7 +41,7 @@ assert-text: ( // Now, explicit return values go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // Intentionally wrong spelling of "NotableStructWithLongName" -write: (".search-input", "-> NotableStructWithLongNamr") +write-into: (".search-input", "-> NotableStructWithLongNamr") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -58,7 +58,7 @@ assert-text: ( // Now, generic correction go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // Intentionally wrong spelling of "NotableStructWithLongName" -write: (".search-input", "NotableStructWithLongNamr, NotableStructWithLongNamr") +write-into: (".search-input", "NotableStructWithLongNamr, NotableStructWithLongNamr") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -75,7 +75,7 @@ assert-text: ( // Now, generic correction plus error go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // Intentionally wrong spelling of "NotableStructWithLongName" -write: (".search-input", "Foo,y") +write-into: (".search-input", "Foo,y") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -91,7 +91,7 @@ assert-text: ( go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // Intentionally wrong spelling of "NotableStructWithLongName" -write: (".search-input", "generic:NotableStructWithLongNamr,y") +write-into: (".search-input", "generic:NotableStructWithLongNamr,y") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml index 70aeda1769aee..d3de77b5635ca 100644 --- a/tests/rustdoc-gui/search-error.goml +++ b/tests/rustdoc-gui/search-error.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-colors", - (theme, error_background), + [theme, error_background], block { // Setting the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} diff --git a/tests/rustdoc-gui/search-filter.goml b/tests/rustdoc-gui/search-filter.goml index 9e2855b5e02f9..8c50322fcd4e4 100644 --- a/tests/rustdoc-gui/search-filter.goml +++ b/tests/rustdoc-gui/search-filter.goml @@ -1,7 +1,7 @@ // Checks that the crate search filtering is handled correctly and changes the results. go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" show-text: true -write: (".search-input", "test") +write-into: (".search-input", "test") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-form-elements.goml b/tests/rustdoc-gui/search-form-elements.goml index 0ea61a4f0eb86..2fc66259291cd 100644 --- a/tests/rustdoc-gui/search-form-elements.goml +++ b/tests/rustdoc-gui/search-form-elements.goml @@ -4,10 +4,10 @@ show-text: true define-function: ( "check-search-colors", - ( + [ theme, border, background, search_input_color, search_input_border_focus, menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color, - ), + ], block { set-local-storage: { "rustdoc-theme": |theme|, diff --git a/tests/rustdoc-gui/search-keyboard.goml b/tests/rustdoc-gui/search-keyboard.goml index f1d8024616bba..707bb8f5faa82 100644 --- a/tests/rustdoc-gui/search-keyboard.goml +++ b/tests/rustdoc-gui/search-keyboard.goml @@ -1,7 +1,7 @@ // Checks that the search tab results work correctly with function signature syntax // First, try a search-by-name go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "Foo") +write-into: (".search-input", "Foo") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-no-result.goml b/tests/rustdoc-gui/search-no-result.goml index e7c6479125633..dda50ec3fb64b 100644 --- a/tests/rustdoc-gui/search-no-result.goml +++ b/tests/rustdoc-gui/search-no-result.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-no-result", - (theme, link, link_hover), + [theme, link, link_hover], block { // Changing theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml index b9d2c8f15cee1..2e7c967d5c333 100644 --- a/tests/rustdoc-gui/search-reexport.goml +++ b/tests/rustdoc-gui/search-reexport.goml @@ -6,7 +6,7 @@ reload: // First we check that the reexport has the correct ID and no background color. assert-text: ("//*[@id='reexport.TheStdReexport']", "pub use ::std as TheStdReexport;") assert-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgba(0, 0, 0, 0)"}) -write: (".search-input", "TheStdReexport") +write-into: (".search-input", "TheStdReexport") // To be SURE that the search will be run. press-key: 'Enter' wait-for: "//a[@class='result-import']" @@ -22,7 +22,7 @@ wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "#494a // We now check that the alias is working as well on the reexport. // To be SURE that the search will be run. press-key: 'Enter' -write: (".search-input", "AliasForTheStdReexport") +write-into: (".search-input", "AliasForTheStdReexport") wait-for: "//a[@class='result-import']" assert-text: ( "a.result-import .result-name", diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 44677dfbfef43..8b0ca7ec97c4d 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -2,7 +2,7 @@ define-function: ( "check-result-color", - (result_kind, color, hover_color), + [result_kind, color, hover_color], block { assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) assert-css: ( @@ -78,60 +78,60 @@ store-value: (hover_background_color, "#3c3c3c") // hover background color store-value: (grey, "#999") call-function: ( - "check-result-color", ( - "keyword", // item kind - "#39afd7", // color of item kind - "#39afd7", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "keyword", // item kind + "color": "#39afd7", // color of item kind + "hover_color": "#39afd7", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "struct", // item kind - "#ffa0a5", // color of item kind - "#ffa0a5", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "struct", // item kind + "color": "#ffa0a5", // color of item kind + "hover_color": "#ffa0a5", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "associatedtype", // item kind - "#39afd7", // color of item kind - "#39afd7", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "associatedtype", // item kind + "color": "#39afd7", // color of item kind + "hover_color": "#39afd7", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "tymethod", // item kind - "#fdd687", // color of item kind - "#fdd687", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "tymethod", // item kind + "color": "#fdd687", // color of item kind + "hover_color": "#fdd687", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "method", // item kind - "#fdd687", // color of item kind - "#fdd687", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "method", // item kind + "color": "#fdd687", // color of item kind + "hover_color": "#fdd687", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "structfield", // item kind - "#0096cf", // color of item kind - "#fff", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "structfield", // item kind + "color": "#0096cf", // color of item kind + "hover_color": "#fff", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "macro", // item kind - "#a37acc", // color of item kind - "#a37acc", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "macro", // item kind + "color": "#a37acc", // color of item kind + "hover_color": "#a37acc", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "fn", // item kind - "#fdd687", // color of item kind - "#fdd687", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "fn", // item kind + "color": "#fdd687", // color of item kind + "hover_color": "#fdd687", // color of hovered/focused item kind + }, ) // Checking the `` container. @@ -190,60 +190,60 @@ store-value: (hover_background_color, "#616161") // hover background color store-value: (grey, "#ccc") call-function: ( - "check-result-color", ( - "keyword", // item kind - "#d2991d", // color of item kind - "#d2991d", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "keyword", // item kind + "color": "#d2991d", // color of item kind + "hover_color": "#d2991d", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "struct", // item kind - "#2dbfb8", // color of item kind - "#2dbfb8", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "struct", // item kind + "color": "#2dbfb8", // color of item kind + "hover_color": "#2dbfb8", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "associatedtype", // item kind - "#d2991d", // color of item kind - "#d2991d", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "associatedtype", // item kind + "color": "#d2991d", // color of item kind + "hover_color": "#d2991d", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "tymethod", // item kind - "#2bab63", // color of item kind - "#2bab63", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "tymethod", // item kind + "color": "#2bab63", // color of item kind + "hover_color": "#2bab63", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "method", // item kind - "#2bab63", // color of item kind - "#2bab63", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "method", // item kind + "color": "#2bab63", // color of item kind + "hover_color": "#2bab63", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "structfield", // item kind - "#ddd", // color of item kind - "#ddd", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "structfield", // item kind + "color": "#ddd", // color of item kind + "hover_color": "#ddd", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "macro", // item kind - "#09bd00", // color of item kind - "#09bd00", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "macro", // item kind + "color": "#09bd00", // color of item kind + "hover_color": "#09bd00", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "fn", // item kind - "#2bab63", // color of item kind - "#2bab63", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "fn", // item kind + "color": "#2bab63", // color of item kind + "hover_color": "#2bab63", // color of hovered/focused item kind + }, ) // Checking the `` container. @@ -287,60 +287,60 @@ store-value: (hover_background_color, "#ccc") // hover background color store-value: (grey, "#999") call-function: ( - "check-result-color", ( - "keyword", // item kind - "#3873ad", // color of item kind - "#3873ad", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "keyword", // item kind + "color": "#3873ad", // color of item kind + "hover_color": "#3873ad", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "struct", // item kind - "#ad378a", // color of item kind - "#ad378a", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "struct", // item kind + "color": "#ad378a", // color of item kind + "hover_color": "#ad378a", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "associatedtype", // item kind - "#3873ad", // color of item kind - "#3873ad", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "associatedtype", // item kind + "color": "#3873ad", // color of item kind + "hover_color": "#3873ad", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "tymethod", // item kind - "#ad7c37", // color of item kind - "#ad7c37", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "tymethod", // item kind + "color": "#ad7c37", // color of item kind + "hover_color": "#ad7c37", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "method", // item kind - "#ad7c37", // color of item kind - "#ad7c37", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "method", // item kind + "color": "#ad7c37", // color of item kind + "hover_color": "#ad7c37", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "structfield", // item kind - "#000", // color of item kind - "#000", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "structfield", // item kind + "color": "#000", // color of item kind + "hover_color": "#000", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "macro", // item kind - "#068000", // color of item kind - "#068000", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "macro", // item kind + "color": "#068000", // color of item kind + "hover_color": "#068000", // color of hovered/focused item kind + }, ) call-function: ( - "check-result-color", ( - "fn", // item kind - "#ad7c37", // color of item kind - "#ad7c37", // color of hovered/focused item kind - ), + "check-result-color", { + "result_kind": "fn", // item kind + "color": "#ad7c37", // color of item kind + "hover_color": "#ad7c37", // color of hovered/focused item kind + }, ) // Checking the `` container. @@ -358,11 +358,11 @@ show-text: true define-function: ( "check-alias", - (theme, alias, grey), + [theme, alias, grey], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: - write: (".search-input", "thisisanalias") + write-into: (".search-input", "thisisanalias") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml index 6ce13b8c3d30f..b1a5548808e01 100644 --- a/tests/rustdoc-gui/search-result-display.goml +++ b/tests/rustdoc-gui/search-result-display.goml @@ -2,7 +2,7 @@ // Checks that the search results have the expected width. go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" set-window-size: (900, 1000) -write: (".search-input", "test") +write-into: (".search-input", "test") // To be SURE that the search will be run. press-key: 'Enter' wait-for: "#crate-search" @@ -69,7 +69,7 @@ assert-css: ("#search", {"width": "640px"}) show-text: true define-function: ( "check-filter", - (theme, border, filter, hover_border, hover_filter), + [theme, border, filter, hover_border, hover_filter], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/search-result-impl-disambiguation.goml b/tests/rustdoc-gui/search-result-impl-disambiguation.goml index 6d12032e891b6..3e49ac33025ee 100644 --- a/tests/rustdoc-gui/search-result-impl-disambiguation.goml +++ b/tests/rustdoc-gui/search-result-impl-disambiguation.goml @@ -5,7 +5,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // This should link to the inherent impl -write: (".search-input", "ZyxwvutMethodDisambiguation -> bool") +write-into: (".search-input", "ZyxwvutMethodDisambiguation -> bool") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -25,7 +25,7 @@ assert: "section:target" go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" // This should link to the trait impl -write: (".search-input", "ZyxwvutMethodDisambiguation, usize -> usize") +write-into: (".search-input", "ZyxwvutMethodDisambiguation, usize -> usize") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml index 1b2be6d4e3e22..370edce2ddd04 100644 --- a/tests/rustdoc-gui/search-result-keyword.goml +++ b/tests/rustdoc-gui/search-result-keyword.goml @@ -1,6 +1,6 @@ // Checks that the "keyword" results have the expected text alongside them. go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "CookieMonster") +write-into: (".search-input", "CookieMonster") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml index 156d8d03ca2d1..7e26229ec6e51 100644 --- a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml +++ b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml @@ -1,7 +1,7 @@ // Checks that the search tab results work correctly with function signature syntax // First, try a search-by-name go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "Foo") +write-into: (".search-input", "Foo") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -23,7 +23,7 @@ wait-for-attribute: ("#search-tabs > button:nth-of-type(3)", {"class": "selected // Now try search-by-return go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "-> String") +write-into: (".search-input", "-> String") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -45,7 +45,7 @@ wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected // Try with a search-by-return with no results go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "-> Something") +write-into: (".search-input", "-> Something") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -55,7 +55,7 @@ assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Return Types" // Try with a search-by-parameter go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "usize,pattern") +write-into: (".search-input", "usize,pattern") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... @@ -65,7 +65,7 @@ assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Parameters", // Try with a search-by-parameter-and-return go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -write: (".search-input", "pattern -> str") +write-into: (".search-input", "pattern -> str") // To be SURE that the search will be run. press-key: 'Enter' // Waiting for the search results to appear... diff --git a/tests/rustdoc-gui/search-tab.goml b/tests/rustdoc-gui/search-tab.goml index b52bb0688c1b5..c33866593c355 100644 --- a/tests/rustdoc-gui/search-tab.goml +++ b/tests/rustdoc-gui/search-tab.goml @@ -4,9 +4,9 @@ show-text: true define-function: ( "check-colors", - (theme, background, background_selected, background_hover, border_bottom, + [theme, background, background_selected, background_hover, border_bottom, border_bottom_selected, border_bottom_hover, border_top, border_top_selected, - border_top_hover), + border_top_hover], block { // Setting the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} @@ -93,12 +93,12 @@ assert-property: ("#search-tabs > button:nth-child(3) > .count", {"offsetWidth": compare-elements-position: ( "#search-tabs > button:nth-child(1) > .count", "#search-tabs > button:nth-child(2) > .count", - ("y") + ["y"] ) compare-elements-position: ( "#search-tabs > button:nth-child(2) > .count", "#search-tabs > button:nth-child(3) > .count", - ("y") + ["y"] ) // Check that counts are beside the titles and haven't wrapped compare-elements-position-near: ( @@ -135,12 +135,12 @@ assert-property: ("#search-tabs > button:nth-child(3) > .count", {"offsetWidth": compare-elements-position: ( "#search-tabs > button:nth-child(1) > .count", "#search-tabs > button:nth-child(2) > .count", - ("y") + ["y"] ) compare-elements-position: ( "#search-tabs > button:nth-child(2) > .count", "#search-tabs > button:nth-child(3) > .count", - ("y") + ["y"] ) // Check that counts are NOT beside the titles; now they have wrapped compare-elements-position-near-false: ( diff --git a/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml index b55a1cfd92bc5..9afde7c61da69 100644 --- a/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml +++ b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml @@ -6,7 +6,7 @@ fail-on-request-error: false define-function: ( "check-setting", - (storage_value, setting_attribute_value, toggle_attribute_value), + [storage_value, setting_attribute_value, toggle_attribute_value], block { assert-local-storage: {"rustdoc-auto-hide-large-items": |storage_value|} click: "#settings-menu" diff --git a/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml b/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml index 5210ad8f793b1..644396ed57826 100644 --- a/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml +++ b/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml @@ -3,7 +3,7 @@ define-function: ( "check-setting", - (storage_value, setting_attribute_value, toggle_attribute_value), + [storage_value, setting_attribute_value, toggle_attribute_value], block { assert-local-storage: {"rustdoc-auto-hide-method-docs": |storage_value|} click: "#settings-menu" diff --git a/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml index ecadd8fa80ede..3c09198dae509 100644 --- a/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml +++ b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml @@ -2,7 +2,7 @@ define-function: ( "check-setting", - (storage_value, setting_attribute_value, toggle_attribute_value), + [storage_value, setting_attribute_value, toggle_attribute_value], block { assert-local-storage: {"rustdoc-auto-hide-trait-implementations": |storage_value|} click: "#settings-menu" diff --git a/tests/rustdoc-gui/setting-go-to-only-result.goml b/tests/rustdoc-gui/setting-go-to-only-result.goml index 45e0b349051ee..f8535477c22d0 100644 --- a/tests/rustdoc-gui/setting-go-to-only-result.goml +++ b/tests/rustdoc-gui/setting-go-to-only-result.goml @@ -2,7 +2,7 @@ define-function: ( "check-setting", - (storage_value, setting_attribute_value), + [storage_value, setting_attribute_value], block { assert-local-storage: {"rustdoc-go-to-only-result": |storage_value|} click: "#settings-menu" @@ -32,7 +32,7 @@ assert-local-storage: {"rustdoc-go-to-only-result": "true"} go-to: "file://" + |DOC_PATH| + "/lib2/index.html" // We enter it into the search. -write: (".search-input", "HasALongTraitWithParams") +write-into: (".search-input", "HasALongTraitWithParams") wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"} assert-window-property: ({"location": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH) diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml index e40c637dcf7dd..0bb21c28cb529 100644 --- a/tests/rustdoc-gui/settings.goml +++ b/tests/rustdoc-gui/settings.goml @@ -304,7 +304,7 @@ wait-for: "#settings" assert-css: (".setting-radio", {"cursor": "pointer"}) assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS) -compare-elements-position: (".sub form", "#settings", ("x")) +compare-elements-position: (".sub form", "#settings", ["x"]) // Check that setting-line has the same margin in this mode as in the popover. assert-css: (".setting-line", {"margin": |setting_line_margin|}) diff --git a/tests/rustdoc-gui/sidebar-links-color.goml b/tests/rustdoc-gui/sidebar-links-color.goml index 774fbcac1e2c4..0edffc51a816d 100644 --- a/tests/rustdoc-gui/sidebar-links-color.goml +++ b/tests/rustdoc-gui/sidebar-links-color.goml @@ -6,12 +6,12 @@ show-text: true define-function: ( "check-colors", - ( + [ theme, struct, struct_hover, struct_hover_background, enum, enum_hover, enum_hover_background, union, union_hover, union_hover_background, trait, trait_hover, trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover, type_hover_background, keyword, keyword_hover, keyword_hover_background, - ), + ], block { set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } reload: diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index d3a82d9ebe6fc..8843de8d7e943 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -57,7 +57,7 @@ show-text: true define-function: ( "check-colors", - (theme, color, background), + [theme, color, background], block { set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} reload: diff --git a/tests/rustdoc-gui/sidebar-source-code-display.goml b/tests/rustdoc-gui/sidebar-source-code-display.goml index 5149d4991f731..41c8e45f4a6d3 100644 --- a/tests/rustdoc-gui/sidebar-source-code-display.goml +++ b/tests/rustdoc-gui/sidebar-source-code-display.goml @@ -30,9 +30,9 @@ show-text: true define-function: ( "check-colors", - ( + [ theme, color, color_hover, background, background_hover, background_toggle, - ), + ], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index d7de43a2243ab..3f7ef643d18e7 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -6,7 +6,7 @@ show-text: true // First, check the sidebar colors. define-function: ( "check-colors", - (theme, color, background_color), + [theme, color, background_color], block { set-local-storage: { "rustdoc-theme": |theme|, diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml index 82b4f2e9429c6..115b1eb323c4d 100644 --- a/tests/rustdoc-gui/sidebar.goml +++ b/tests/rustdoc-gui/sidebar.goml @@ -6,7 +6,7 @@ show-text: true // First, check the sidebar colors. define-function: ( "check-colors", - (theme, color, background_color), + [theme, color, background_color], block { set-local-storage: { "rustdoc-theme": |theme|, diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml index 8b4d7617e0cdb..e29d123d2270b 100644 --- a/tests/rustdoc-gui/source-code-page.goml +++ b/tests/rustdoc-gui/source-code-page.goml @@ -21,7 +21,7 @@ assert-attribute-false: (".src-line-numbers > a:nth-child(7)", {"class": "line-h define-function: ( "check-colors", - (theme, color, background_color, highlight_color, highlight_background_color), + [theme, color, background_color, highlight_color, highlight_background_color], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: @@ -61,7 +61,7 @@ call-function: ("check-colors", { }) // This is to ensure that the content is correctly align with the line numbers. -compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y")) +compare-elements-position: ("//*[@id='1']", ".rust > code > span", ["y"]) // Check the `href` property so that users can treat anchors as links. assert-property: (".src-line-numbers > a:nth-child(1)", { "href": |DOC_PATH| + "/src/test_docs/lib.rs.html#1" @@ -122,7 +122,7 @@ store-property: ( ) define-function: ( "check-sidebar-dir-entry", - (x, y), + [x, y], block { assert: "details:first-of-type.dir-entry[open] > summary::marker" assert-css: ("#src-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"}) diff --git a/tests/rustdoc-gui/stab-badge.goml b/tests/rustdoc-gui/stab-badge.goml index bb3d2aaa3dca0..46df0946c4592 100644 --- a/tests/rustdoc-gui/stab-badge.goml +++ b/tests/rustdoc-gui/stab-badge.goml @@ -3,7 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" show-text: true define-function: ( "check-badge", - (theme, background, color), + [theme, background, color], block { set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml index 26071df8d044e..0f8f770936356 100644 --- a/tests/rustdoc-gui/target.goml +++ b/tests/rustdoc-gui/target.goml @@ -7,7 +7,7 @@ assert: "#method\.a_method:target" define-function: ( "check-style", - (theme, background, border), + [theme, background, border], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/toggle-docs.goml b/tests/rustdoc-gui/toggle-docs.goml index 9ea6d9b18f4c7..cfd18bd2e14f3 100644 --- a/tests/rustdoc-gui/toggle-docs.goml +++ b/tests/rustdoc-gui/toggle-docs.goml @@ -49,7 +49,7 @@ assert-attribute: ("details.toggle", {"open": ""}, ALL) show-text: true define-function: ( "check-color", - (theme, filter), + [theme, filter], block { // Setting the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml index a97cc98897ae2..3709aa102661f 100644 --- a/tests/rustdoc-gui/type-declation-overflow.goml +++ b/tests/rustdoc-gui/type-declation-overflow.goml @@ -47,18 +47,18 @@ assert-css: (".mobile-topbar h2", {"overflow-x": "hidden"}) // On desktop, they wrap when too big. set-window-size: (1100, 800) go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html" -compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y")) +compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"]) go-to: "file://" + |DOC_PATH| + "/lib2/index.html" -compare-elements-position: (".main-heading h1", ".main-heading .out-of-band", ("y")) +compare-elements-position: (".main-heading h1", ".main-heading .out-of-band", ["y"]) // make sure there is a gap between them compare-elements-position-near-false: (".main-heading h1", ".main-heading .out-of-band", {"x": 550}) // On mobile, they always wrap. set-window-size: (600, 600) go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html" -compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y")) +compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"]) go-to: "file://" + |DOC_PATH| + "/lib2/index.html" -compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y")) +compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ["y"]) // Now we will check that the scrolling is working. // First on an item with "hidden methods". diff --git a/tests/rustdoc-gui/unsafe-fn.goml b/tests/rustdoc-gui/unsafe-fn.goml index 8d26f15f37f1b..83503121a0469 100644 --- a/tests/rustdoc-gui/unsafe-fn.goml +++ b/tests/rustdoc-gui/unsafe-fn.goml @@ -13,7 +13,7 @@ define-function: ( "sup-check", // `theme` is the theme being tested. // `color` is the expected color of the `` element. - (theme, color), + [theme, color], block { // Set the theme. set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} @@ -23,6 +23,15 @@ define-function: ( }, ) -call-function: ("sup-check", ("ayu", "#c5c5c5")) -call-function: ("sup-check", ("dark", "#ddd")) -call-function: ("sup-check", ("light", "black")) +call-function: ("sup-check", { + "theme": "ayu", + "color": "#c5c5c5", +}) +call-function: ("sup-check", { + "theme": "dark", + "color": "#ddd", +}) +call-function: ("sup-check", { + "theme": "light", + "color": "black", +}) diff --git a/tests/rustdoc-gui/warning-block.goml b/tests/rustdoc-gui/warning-block.goml index 10e206049f53c..a5a47f868db22 100644 --- a/tests/rustdoc-gui/warning-block.goml +++ b/tests/rustdoc-gui/warning-block.goml @@ -5,7 +5,7 @@ show-text: true store-value: (default_y_pos, 5) define-function: ( "check-warning", - (theme, color, border_color), + [theme, color, border_color], block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: diff --git a/tests/rustdoc-gui/where-whitespace.goml b/tests/rustdoc-gui/where-whitespace.goml index da104fa40116f..823ce9704076b 100644 --- a/tests/rustdoc-gui/where-whitespace.goml +++ b/tests/rustdoc-gui/where-whitespace.goml @@ -3,25 +3,25 @@ go-to: "file://" + |DOC_PATH| + "/lib2/trait.Whitespace.html" show-text: true // First, we check in the trait definition if the where clause is "on its own" (not on the same // line than "pub trait Whitespace"). -compare-elements-position-false: (".item-decl code", "div.where", ("y")) +compare-elements-position-false: (".item-decl code", "div.where", ["y"]) // And that the code following it isn't on the same line either. -compare-elements-position-false: (".item-decl .fn", "div.where", ("y")) +compare-elements-position-false: (".item-decl .fn", "div.where", ["y"]) go-to: "file://" + |DOC_PATH| + "/lib2/struct.WhereWhitespace.html" // We make the screen a bit wider to ensure that the trait impl is on one line. set-window-size: (915, 915) -compare-elements-position-false: ("#method\.new .fn", "#method\.new div.where", ("y")) +compare-elements-position-false: ("#method\.new .fn", "#method\.new div.where", ["y"]) // We ensure that both the trait name and the struct name are on the same line in // "impl Whitespace<&K> for WhereWhitespace". compare-elements-position: ( "#trait-implementations-list .impl h3 .trait", "#trait-implementations-list .impl h3 .struct", - ("y"), + ["y"], ) // And we now check that the where condition isn't on the same line. compare-elements-position-false: ( "#trait-implementations-list .impl h3 .trait", "#trait-implementations-list .impl h3 div.where", - ("y"), + ["y"], ) From 0bb1ec729f5caf04b93a22d6aabda24bf187a12b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Apr 2024 10:42:32 +0200 Subject: [PATCH 08/12] Remove redundant code comments --- tests/rustdoc-gui/search-result-color.goml | 144 ++++++++++----------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 8b0ca7ec97c4d..1a19ea2d84327 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -79,58 +79,58 @@ store-value: (grey, "#999") call-function: ( "check-result-color", { - "result_kind": "keyword", // item kind - "color": "#39afd7", // color of item kind - "hover_color": "#39afd7", // color of hovered/focused item kind + "result_kind": "keyword", + "color": "#39afd7", + "hover_color": "#39afd7", }, ) call-function: ( "check-result-color", { - "result_kind": "struct", // item kind - "color": "#ffa0a5", // color of item kind - "hover_color": "#ffa0a5", // color of hovered/focused item kind + "result_kind": "struct", + "color": "#ffa0a5", + "hover_color": "#ffa0a5", }, ) call-function: ( "check-result-color", { - "result_kind": "associatedtype", // item kind - "color": "#39afd7", // color of item kind - "hover_color": "#39afd7", // color of hovered/focused item kind + "result_kind": "associatedtype", + "color": "#39afd7", + "hover_color": "#39afd7", }, ) call-function: ( "check-result-color", { - "result_kind": "tymethod", // item kind - "color": "#fdd687", // color of item kind - "hover_color": "#fdd687", // color of hovered/focused item kind + "result_kind": "tymethod", + "color": "#fdd687", + "hover_color": "#fdd687", }, ) call-function: ( "check-result-color", { - "result_kind": "method", // item kind - "color": "#fdd687", // color of item kind - "hover_color": "#fdd687", // color of hovered/focused item kind + "result_kind": "method", + "color": "#fdd687", + "hover_color": "#fdd687", }, ) call-function: ( "check-result-color", { - "result_kind": "structfield", // item kind - "color": "#0096cf", // color of item kind - "hover_color": "#fff", // color of hovered/focused item kind + "result_kind": "structfield", + "color": "#0096cf", + "hover_color": "#fff", }, ) call-function: ( "check-result-color", { - "result_kind": "macro", // item kind - "color": "#a37acc", // color of item kind - "hover_color": "#a37acc", // color of hovered/focused item kind + "result_kind": "macro", + "color": "#a37acc", + "hover_color": "#a37acc", }, ) call-function: ( "check-result-color", { - "result_kind": "fn", // item kind - "color": "#fdd687", // color of item kind - "hover_color": "#fdd687", // color of hovered/focused item kind + "result_kind": "fn", + "color": "#fdd687", + "hover_color": "#fdd687", }, ) @@ -191,58 +191,58 @@ store-value: (grey, "#ccc") call-function: ( "check-result-color", { - "result_kind": "keyword", // item kind - "color": "#d2991d", // color of item kind - "hover_color": "#d2991d", // color of hovered/focused item kind + "result_kind": "keyword", + "color": "#d2991d", + "hover_color": "#d2991d", }, ) call-function: ( "check-result-color", { - "result_kind": "struct", // item kind - "color": "#2dbfb8", // color of item kind - "hover_color": "#2dbfb8", // color of hovered/focused item kind + "result_kind": "struct", + "color": "#2dbfb8", + "hover_color": "#2dbfb8", }, ) call-function: ( "check-result-color", { - "result_kind": "associatedtype", // item kind - "color": "#d2991d", // color of item kind - "hover_color": "#d2991d", // color of hovered/focused item kind + "result_kind": "associatedtype", + "color": "#d2991d", + "hover_color": "#d2991d", }, ) call-function: ( "check-result-color", { - "result_kind": "tymethod", // item kind - "color": "#2bab63", // color of item kind - "hover_color": "#2bab63", // color of hovered/focused item kind + "result_kind": "tymethod", + "color": "#2bab63", + "hover_color": "#2bab63", }, ) call-function: ( "check-result-color", { - "result_kind": "method", // item kind - "color": "#2bab63", // color of item kind - "hover_color": "#2bab63", // color of hovered/focused item kind + "result_kind": "method", + "color": "#2bab63", + "hover_color": "#2bab63", }, ) call-function: ( "check-result-color", { - "result_kind": "structfield", // item kind - "color": "#ddd", // color of item kind - "hover_color": "#ddd", // color of hovered/focused item kind + "result_kind": "structfield", + "color": "#ddd", + "hover_color": "#ddd", }, ) call-function: ( "check-result-color", { - "result_kind": "macro", // item kind - "color": "#09bd00", // color of item kind - "hover_color": "#09bd00", // color of hovered/focused item kind + "result_kind": "macro", + "color": "#09bd00", + "hover_color": "#09bd00", }, ) call-function: ( "check-result-color", { - "result_kind": "fn", // item kind - "color": "#2bab63", // color of item kind - "hover_color": "#2bab63", // color of hovered/focused item kind + "result_kind": "fn", + "color": "#2bab63", + "hover_color": "#2bab63", }, ) @@ -288,58 +288,58 @@ store-value: (grey, "#999") call-function: ( "check-result-color", { - "result_kind": "keyword", // item kind - "color": "#3873ad", // color of item kind - "hover_color": "#3873ad", // color of hovered/focused item kind + "result_kind": "keyword", + "color": "#3873ad", + "hover_color": "#3873ad", }, ) call-function: ( "check-result-color", { - "result_kind": "struct", // item kind - "color": "#ad378a", // color of item kind - "hover_color": "#ad378a", // color of hovered/focused item kind + "result_kind": "struct", + "color": "#ad378a", + "hover_color": "#ad378a", }, ) call-function: ( "check-result-color", { - "result_kind": "associatedtype", // item kind - "color": "#3873ad", // color of item kind - "hover_color": "#3873ad", // color of hovered/focused item kind + "result_kind": "associatedtype", + "color": "#3873ad", + "hover_color": "#3873ad", }, ) call-function: ( "check-result-color", { - "result_kind": "tymethod", // item kind - "color": "#ad7c37", // color of item kind - "hover_color": "#ad7c37", // color of hovered/focused item kind + "result_kind": "tymethod", + "color": "#ad7c37", + "hover_color": "#ad7c37", }, ) call-function: ( "check-result-color", { - "result_kind": "method", // item kind - "color": "#ad7c37", // color of item kind - "hover_color": "#ad7c37", // color of hovered/focused item kind + "result_kind": "method", + "color": "#ad7c37", + "hover_color": "#ad7c37", }, ) call-function: ( "check-result-color", { - "result_kind": "structfield", // item kind - "color": "#000", // color of item kind - "hover_color": "#000", // color of hovered/focused item kind + "result_kind": "structfield", + "color": "#000", + "hover_color": "#000", }, ) call-function: ( "check-result-color", { - "result_kind": "macro", // item kind - "color": "#068000", // color of item kind - "hover_color": "#068000", // color of hovered/focused item kind + "result_kind": "macro", + "color": "#068000", + "hover_color": "#068000", }, ) call-function: ( "check-result-color", { - "result_kind": "fn", // item kind - "color": "#ad7c37", // color of item kind - "hover_color": "#ad7c37", // color of hovered/focused item kind + "result_kind": "fn", + "color": "#ad7c37", + "hover_color": "#ad7c37", }, ) From b4993c47f2f1348356d87c92ea54fd20fcd71cb7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 2 Apr 2024 14:10:06 +0000 Subject: [PATCH 09/12] Prefer `UnordSet` over `FxHashSet` where possible --- compiler/rustc_mir_transform/src/coroutine/by_move_body.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index e0bbd582d88c2..9201ad401521a 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -3,7 +3,7 @@ //! be a coroutine body that takes all of its upvars by-move, and which we stash //! into the `CoroutineInfo` for all coroutines returned by coroutine-closures. -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::unord::UnordSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir, MirPass}; @@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { return; } - let mut by_ref_fields = FxIndexSet::default(); + let mut by_ref_fields = UnordSet::default(); let by_move_upvars = Ty::new_tup_from_iter( tcx, tcx.closure_captures(coroutine_def_id).iter().enumerate().map(|(idx, capture)| { @@ -73,7 +73,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { struct MakeByMoveBody<'tcx> { tcx: TyCtxt<'tcx>, - by_ref_fields: FxIndexSet, + by_ref_fields: UnordSet, by_move_coroutine_ty: Ty<'tcx>, } From 6f3cc0903c7d540acc10ea13fa2cf6aaec8f64cd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 2 Apr 2024 14:13:05 +0000 Subject: [PATCH 10/12] Avoid an `is_empty()` followed by an index op in favor of a single fallible op --- compiler/rustc_mir_transform/src/coroutine/by_move_body.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 9201ad401521a..99dbb34226834 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -89,11 +89,11 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { location: mir::Location, ) { if place.local == ty::CAPTURE_STRUCT_LOCAL - && !place.projection.is_empty() - && let mir::ProjectionElem::Field(idx, ty) = place.projection[0] + && let Some((&mir::ProjectionElem::Field(idx, ty), projection)) = + place.projection.split_first() && self.by_ref_fields.contains(&idx) { - let (begin, end) = place.projection[1..].split_first().unwrap(); + let (begin, end) = projection.split_first().unwrap(); // FIXME(async_closures): I'm actually a bit surprised to see that we always // initially deref the by-ref upvars. If this is not actually true, then we // will at least get an ICE that explains why this isn't true :^) From a272007a209a4327ad8122af1ad9f9620f04724e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 2 Apr 2024 07:55:52 -0700 Subject: [PATCH 11/12] Clean up src/librustdoc/html/render/search_index/encode.rs Co-authored-by: Guillaume Gomez --- .../html/render/search_index/encode.rs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index af5eccd5bedc6..54407c614c4c7 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -92,24 +92,23 @@ impl Container { r += !chunk & u64::from((chunk << 1).count_ones()); r += !next_chunk & u64::from((chunk >> 63).count_ones()); } - if (2 + 4 * r) < 8192 { - let bits = std::mem::replace(bits, Box::new([0; 1024])); - *self = Container::Run(Vec::new()); - for (i, bits) in bits.iter().copied().enumerate() { - if bits == 0 { - continue; - } - for j in 0..64 { - let value = (u16::try_from(i).unwrap() << 6) | j; - if bits & (1 << j) != 0 { - self.push(value); - } + if (2 + 4 * r) >= 8192 { + return false; + } + let bits = std::mem::replace(bits, Box::new([0; 1024])); + *self = Container::Run(Vec::new()); + for (i, bits) in bits.iter().copied().enumerate() { + if bits == 0 { + continue; + } + for j in 0..64 { + let value = (u16::try_from(i).unwrap() << 6) | j; + if bits & (1 << j) != 0 { + self.push(value); } } - true - } else { - false } + true } Container::Array(array) if array.len() <= 5 => false, Container::Array(array) => { @@ -121,16 +120,15 @@ impl Container { } prev = Some(value); } - if 2 + 4 * r < 2 * array.len() + 2 { - let array = std::mem::replace(array, Vec::new()); - *self = Container::Run(Vec::new()); - for value in array { - self.push(value); - } - true - } else { - false + if 2 + 4 * r >= 2 * array.len() + 2 { + return false; + } + let array = std::mem::replace(array, Vec::new()); + *self = Container::Run(Vec::new()); + for value in array { + self.push(value); } + true } Container::Run(_) => true, } From 858a1dfd5bc7c27655d07d45c792fccb4ac0c43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Tue, 2 Apr 2024 18:02:06 +0200 Subject: [PATCH 12/12] Remove dangling `.mir.stderr` and `.thir.stderr` test files --- ...const-extern-fn-requires-unsafe.mir.stderr | 19 --- ...onst-extern-fn-requires-unsafe.thir.stderr | 19 --- .../fn-ptr.mir.stderr | 23 ---- .../fn-ptr.thir.stderr | 23 ---- .../safe-calls.mir.stderr | 115 ------------------ .../safe-calls.thir.stderr | 115 ------------------ 6 files changed, 314 deletions(-) delete mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr delete mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr delete mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr delete mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr delete mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr delete mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr deleted file mode 100644 index 34ec8aadbcf3b..0000000000000 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:12:5 - | -LL | foo(); - | ^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:9:17 - | -LL | let a: [u8; foo()]; - | ^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr deleted file mode 100644 index e6b8173eb051a..0000000000000 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:12:5 - | -LL | foo(); - | ^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block - --> $DIR/const-extern-fn-requires-unsafe.rs:9:17 - | -LL | let a: [u8; foo()]; - | ^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr deleted file mode 100644 index 7bbd4e158982f..0000000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/fn-ptr.rs:11:21 - | -LL | #[target_feature(enable = "sse2")] - | ---------------------------------- `#[target_feature]` added here -... -LL | let foo: fn() = foo; - | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers - | | - | expected due to this - | - = note: expected fn pointer `fn()` - found fn item `fn() {foo}` - = note: fn items are distinct from fn pointers - = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers -help: consider casting to a fn pointer - | -LL | let foo: fn() = foo as fn(); - | ~~~~~~~~~~~ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr deleted file mode 100644 index 7bbd4e158982f..0000000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/fn-ptr.rs:11:21 - | -LL | #[target_feature(enable = "sse2")] - | ---------------------------------- `#[target_feature]` added here -... -LL | let foo: fn() = foo; - | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers - | | - | expected due to this - | - = note: expected fn pointer `fn()` - found fn item `fn() {foo}` - = note: fn items are distinct from fn pointers - = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers -help: consider casting to a fn pointer - | -LL | let foo: fn() = foo as fn(); - | ~~~~~~~~~~~ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr deleted file mode 100644 index cabc475fa61cf..0000000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:28:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:31:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:34:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:41:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:44:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:51:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:54:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:57:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:70:15 - | -LL | const _: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:74:15 - | -LL | const _: () = sse2_and_fxsr(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr - = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` - -error: call to function with `#[target_feature]` is unsafe and requires unsafe block (error E0133) - --> $DIR/safe-calls.rs:82:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` -note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/safe-calls.rs:81:1 - | -LL | unsafe fn needs_unsafe_block() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/safe-calls.rs:78:8 - | -LL | #[deny(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr deleted file mode 100644 index 13b58fde862d5..0000000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:28:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:31:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:34:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:41:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:44:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 - -error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:51:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:54:5 - | -LL | avx_bmi2(); - | ^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 - -error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:57:5 - | -LL | Quux.avx_bmi2(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 - -error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:70:15 - | -LL | const _: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` - -error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:74:15 - | -LL | const _: () = sse2_and_fxsr(); - | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr - = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` - -error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) - --> $DIR/safe-calls.rs:82:5 - | -LL | sse2(); - | ^^^^^^ call to function with `#[target_feature]` - | - = help: in order for the call to be safe, the context requires the following additional target feature: sse2 - = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` -note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/safe-calls.rs:81:1 - | -LL | unsafe fn needs_unsafe_block() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/safe-calls.rs:78:8 - | -LL | #[deny(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors - -For more information about this error, try `rustc --explain E0133`.