From d80ac14fe69676c34efdec0c1cc589d28cd03ab1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 15:37:00 +0200 Subject: [PATCH 01/17] Extend rustdoc-js tester to allow to test multiple queries in one file --- src/tools/rustdoc-js/tester.js | 98 ++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 03f06fc1c6c71..72bc496c5b5d3 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -181,7 +181,7 @@ function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { for (var i = 0; i < thingsToLoad.length; ++i) { var tmp = funcToCall(fileContent, thingsToLoad[i]); if (tmp === null) { - console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); + console.log('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); process.exit(1); } content += tmp; @@ -223,7 +223,8 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { searchIndex.pop(); } searchIndex.pop(); - searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;'); + var fullSearchIndex = searchIndex.join("\n") + '\nexports.rawSearchIndex = searchIndex;'; + searchIndex = loadContent(fullSearchIndex); var finalJS = ""; var arraysToLoad = ["itemTypes"]; @@ -235,7 +236,7 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index. var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", - "getQuery", "buildIndex", "execQuery", "execSearch"]; + "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch"]; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; @@ -245,24 +246,19 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); - var index = loaded.buildIndex(searchIndex.searchIndex); + var index = loaded.buildIndex(searchIndex.rawSearchIndex); + // We make it "global" so that the "loaded.execSearch" function will find it. + rawSearchIndex = searchIndex.rawSearchIndex; return [loaded, index]; } -function runChecks(testFile, loaded, index) { - var errors = 0; - var loadedFile = loadContent( - readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); - - const expected = loadedFile.EXPECTED; - const query = loadedFile.QUERY; +function runSearch(query, expected, index, loaded, loadedFile, queryName) { const filter_crate = loadedFile.FILTER_CRATE; const ignore_order = loadedFile.ignore_order; const exact_check = loadedFile.exact_check; - const should_fail = loadedFile.should_fail; - var results = loaded.execSearch(loaded.getQuery(query), index); + var results = loaded.execSearch(loaded.getQuery(query), index, filter_crate); var error_text = []; for (var key in expected) { @@ -278,32 +274,68 @@ function runChecks(testFile, loaded, index) { for (var i = 0; i < entry.length; ++i) { var entry_pos = lookForEntry(entry[i], results[key]); if (entry_pos === null) { - error_text.push("==> Result not found in '" + key + "': '" + + error_text.push(queryName + "==> Result not found in '" + key + "': '" + JSON.stringify(entry[i]) + "'"); } else if (exact_check === true && prev_pos + 1 !== entry_pos) { - error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " + - "expected '" + JSON.stringify(entry[i]) + "' but found '" + + error_text.push(queryName + "==> Exact check failed at position " + (prev_pos + 1) + + ": expected '" + JSON.stringify(entry[i]) + "' but found '" + JSON.stringify(results[key][i]) + "'"); } else if (ignore_order === false && entry_pos < prev_pos) { - error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + - " before '" + JSON.stringify(results[key][entry_pos]) + "'"); + error_text.push(queryName + "==> '" + JSON.stringify(entry[i]) + "' was supposed " + + "to be before '" + JSON.stringify(results[key][entry_pos]) + "'"); } else { prev_pos = entry_pos; } } } - if (error_text.length === 0 && should_fail === true) { - errors += 1; - console.error("FAILED"); - console.error("==> Test was supposed to fail but all items were found..."); - } else if (error_text.length !== 0 && should_fail === false) { - errors += 1; - console.error("FAILED"); - console.error(error_text.join("\n")); + return error_text; +} + +function checkResult(error_text, loadedFile, displaySuccess) { + if (error_text.length === 0 && loadedFile.should_fail === true) { + console.log("FAILED"); + console.log("==> Test was supposed to fail but all items were found..."); + } else if (error_text.length !== 0 && loadedFile.should_fail === false) { + console.log("FAILED"); + console.log(error_text.join("\n")); } else { + if (displaySuccess) { + console.log("OK"); + } + return 0; + } + return 1; +} + +function runChecks(testFile, loaded, index) { + var loadedFile = loadContent( + readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); + + const expected = loadedFile.EXPECTED; + const query = loadedFile.QUERY; + + if (Array.isArray(query)) { + if (!Array.isArray(expected)) { + console.log("FAILED"); + console.log("==> If QUERY variable is an array, EXPECTED should be an array too"); + return 1; + } else if (query.length !== expected.length) { + console.log("FAILED"); + console.log("==> QUERY variable should have the same length as EXPECTED"); + return 1; + } + for (var i = 0; i < query.length; ++i) { + var error_text = runSearch(query[i], expected[i], index, loaded, loadedFile, + "[ query `" + query[i] + "`]"); + if (checkResult(error_text, loadedFile, false) !== 0) { + return 1; + } + } console.log("OK"); + return 0; } - return errors; + var error_text = runSearch(query, expected, index, loaded, loadedFile, ""); + return checkResult(error_text, loadedFile, true); } function load_files(doc_folder, resource_suffix, crate) { @@ -349,7 +381,7 @@ function parseOptions(args) { || args[i] === "--crate-name") { i += 1; if (i >= args.length) { - console.error("Missing argument after `" + args[i - 1] + "` option."); + console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } opts[correspondances[args[i - 1]]] = args[i]; @@ -357,17 +389,17 @@ function parseOptions(args) { showHelp(); process.exit(0); } else { - console.error("Unknown option `" + args[i] + "`."); - console.error("Use `--help` to see the list of options"); + console.log("Unknown option `" + args[i] + "`."); + console.log("Use `--help` to see the list of options"); return null; } } if (opts["doc_folder"].length < 1) { - console.error("Missing `--doc-folder` option."); + console.log("Missing `--doc-folder` option."); } else if (opts["crate_name"].length < 1) { - console.error("Missing `--crate-name` option."); + console.log("Missing `--crate-name` option."); } else if (opts["test_folder"].length < 1 && opts["test_file"].length < 1) { - console.error("At least one of `--test-folder` or `--test-file` option is required."); + console.log("At least one of `--test-folder` or `--test-file` option is required."); } else { return opts; } From 7590c393dee055e9ce97f8a5f993fa0cc7e56217 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:53:40 +0200 Subject: [PATCH 02/17] Improve doc alias JS code --- src/librustdoc/html/static/main.js | 73 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a023d5a2d95f1..411d2d44059b2 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -963,6 +963,50 @@ function getSearchElement() { return itemTypes[ty.ty] + ty.path + ty.name; } + function handleAliases(ret, query, filterCrates) { + if (ALIASES) { + var aliases = []; + if (filterCrates !== undefined && + ALIASES[filterCrates] && + ALIASES[filterCrates][query.search]) { + aliases = ALIASES[filterCrates][query.search]; + } else { + Object.keys(ALIASES).forEach(function(crate) { + if (ALIASES[crate][query.search]) { + for (var i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push(ALIASES[crate][query.search][i]); + } + } + }); + } + aliases.sort(function(aaa, bbb) { + if (aaa.path < bbb.path) { + return 1; + } else if (aaa.path === bbb.path) { + return 0; + } + return -1; + }); + for (var i = 0; i < aliases.length; ++i) { + var alias = aliases[i]; + alias.is_alias = true; + if (typeof alias.parent === "number") { + alias.parent = rawSearchIndex[alias.crate].p[alias.parent]; + } + alias.alias = query.raw; + alias.path = alias.p || alias.crate; + var res = buildHrefAndPath(aliases[i]); + alias.displayPath = pathSplitter(res[0]); + alias.fullPath = alias.displayPath + alias.name; + alias.href = res[1]; + ret.others.unshift(alias); + if (ret.others.length > MAX_RESULTS) { + ret.others.pop(); + } + } + } + } + // quoted values mean literal search var nSearchWords = searchWords.length; var i; @@ -1190,23 +1234,7 @@ function getSearchElement() { "returned": sortResults(results_returned, true), "others": sortResults(results), }; - if (ALIASES && ALIASES[window.currentCrate] && - ALIASES[window.currentCrate][query.raw]) { - var aliases = ALIASES[window.currentCrate][query.raw]; - for (i = 0; i < aliases.length; ++i) { - aliases[i].is_alias = true; - aliases[i].alias = query.raw; - aliases[i].path = aliases[i].p; - var res = buildHrefAndPath(aliases[i]); - aliases[i].displayPath = pathSplitter(res[0]); - aliases[i].fullPath = aliases[i].displayPath + aliases[i].name; - aliases[i].href = res[1]; - ret.others.unshift(aliases[i]); - if (ret.others.length > MAX_RESULTS) { - ret.others.pop(); - } - } - } + handleAliases(ret, query, filterCrates); return ret; } @@ -1599,13 +1627,12 @@ function getSearchElement() { "returned": mergeArrays(results.returned), "others": mergeArrays(results.others), }; - } else { - return { - "in_args": results.in_args[0], - "returned": results.returned[0], - "others": results.others[0], - }; } + return { + "in_args": results.in_args[0], + "returned": results.returned[0], + "others": results.others[0], + }; } function getFilterCrates() { From cf41b1d3a5fc5e4c209ab101b159095178dea916 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:54:06 +0200 Subject: [PATCH 03/17] Improve doc alias discovery --- src/librustdoc/html/render.rs | 11 +++- src/librustdoc/html/render/cache.rs | 89 +++++++++++++++++------------ 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 666e59b9a045e..4ed367a5c80d3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -278,7 +278,7 @@ pub struct RenderInfo { /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] -struct IndexItem { +pub struct IndexItem { ty: ItemType, name: String, path: String, @@ -293,7 +293,12 @@ impl Serialize for IndexItem { where S: Serializer, { - assert_eq!(self.parent.is_some(), self.parent_idx.is_some()); + assert_eq!( + self.parent.is_some(), + self.parent_idx.is_some(), + "`{}` is missing idx", + self.name + ); (self.ty, &self.name, &self.path, &self.desc, self.parent_idx, &self.search_type) .serialize(serializer) @@ -836,7 +841,7 @@ themePicker.onblur = handleThemeButtonsBlur; { let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); let mut output = String::with_capacity(100); - for (alias, items) in &cx.cache.aliases { + for (alias, items) in cx.cache.get_aliases() { if items.is_empty() { continue; } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 5b09029122718..17003334bc856 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -120,7 +120,7 @@ crate struct Cache { /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. - pub(super) aliases: FxHashMap>, + pub(super) aliases: FxHashMap>, } impl Cache { @@ -311,7 +311,7 @@ impl DocFolder for Cache { }; match parent { - (parent, Some(path)) if is_inherent_impl_item || (!self.stripped_mod) => { + (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => { debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, @@ -327,6 +327,21 @@ impl DocFolder for Cache { parent_idx: None, search_type: get_index_search_type(&item), }); + + for alias in item + .attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() + { + self.aliases + .entry(alias.to_lowercase()) + .or_insert(Vec::with_capacity(1)) + .push(self.search_index.len() - 1); + } } } (Some(parent), None) if is_inherent_impl_item => { @@ -363,6 +378,9 @@ impl DocFolder for Cache { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) + | clean::StructFieldItem(..) + | clean::TyMethodItem(..) + | clean::MethodItem(..) if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice @@ -376,11 +394,8 @@ impl DocFolder for Cache { { self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } - self.add_aliases(&item); } - clean::PrimitiveItem(..) => { - self.add_aliases(&item); self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } @@ -489,36 +504,23 @@ impl DocFolder for Cache { } impl Cache { - fn add_aliases(&mut self, item: &clean::Item) { - if item.def_id.index == CRATE_DEF_INDEX { - return; - } - if let Some(ref item_name) = item.name { - let path = self - .paths - .get(&item.def_id) - .map(|p| p.0[..p.0.len() - 1].join("::")) - .unwrap_or("std".to_owned()); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { - self.aliases.entry(alias).or_insert(Vec::with_capacity(1)).push(IndexItem { - ty: item.type_(), - name: item_name.to_string(), - path: path.clone(), - desc: shorten(plain_summary_line(item.doc_value())), - parent: None, - parent_idx: None, - search_type: get_index_search_type(&item), - }); - } - } + pub fn get_aliases<'a>(&'a self) -> FxHashMap> { + self.aliases + .iter() + .map(|(k, values)| { + ( + k.clone(), + values + .iter() + .filter(|v| { + let x = &self.search_index[**v]; + x.parent_idx.is_some() == x.parent.is_some() + }) + .map(|v| &self.search_index[*v]) + .collect::>(), + ) + }) + .collect() } } @@ -567,7 +569,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_paths = vec![]; - let Cache { ref mut search_index, ref orphan_impl_items, ref paths, .. } = *cache; + let Cache { ref mut search_index, ref orphan_impl_items, ref paths, ref mut aliases, .. } = + *cache; // Attach all orphan items to the type's definition if the type // has since been learned. @@ -582,6 +585,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); + for alias in item + .attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() + { + aliases + .entry(alias.to_lowercase()) + .or_insert(Vec::with_capacity(1)) + .push(search_index.len() - 1); + } } } From 3a0727e84e29318ee41eb63bac27bfc1a379bfc5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:27:24 +0200 Subject: [PATCH 04/17] Add more tests for doc aliases --- src/test/rustdoc-js/doc-alias.js | 237 +++++++++++++++++++++++++++++++ src/test/rustdoc-js/doc-alias.rs | 80 +++++++++++ 2 files changed, 317 insertions(+) create mode 100644 src/test/rustdoc-js/doc-alias.js create mode 100644 src/test/rustdoc-js/doc-alias.rs diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js new file mode 100644 index 0000000000000..e6310b625e533 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias.js @@ -0,0 +1,237 @@ +// exact-check + +const QUERY = [ + 'StructItem', + 'StructFieldItem', + 'StructMethodItem', + 'ImplTraitItem', + 'ImplAssociatedConstItem', + 'ImplTraitFunction', + 'EnumItem', + 'VariantItem', + 'EnumMethodItem', + 'TypedefItem', + 'TraitItem', + 'TraitTypeItem', + 'AssociatedConstItem', + 'TraitFunctionItem', + 'FunctionItem', + 'ModuleItem', + 'ConstItem', + 'StaticItem', + 'UnionItem', + 'UnionFieldItem', + 'UnionMethodItem', + 'MacroItem', +]; + +const EXPECTED = [ + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Struct', + 'alias': 'StructItem', + 'href': '../doc_alias/struct.Struct.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'field', + 'alias': 'StructFieldItem', + 'href': '../doc_alias/struct.Struct.html#structfield.field' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'method', + 'alias': 'StructMethodItem', + 'href': '../doc_alias/struct.Struct.html#method.method' + }, + ], + }, + { + // ImplTraitItem + 'others': [], + }, + { + // ImplAssociatedConstItem + 'others': [], + }, + { + // ImplTraitFunction + 'others': [], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Enum', + 'alias': 'EnumItem', + 'href': '../doc_alias/enum.Enum.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Enum', + 'name': 'Variant', + 'alias': 'VariantItem', + 'href': '../doc_alias/enum.Enum.html#variant.Variant' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Enum', + 'name': 'method', + 'alias': 'EnumMethodItem', + 'href': '../doc_alias/enum.Enum.html#method.method' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Typedef', + 'alias': 'TypedefItem', + 'href': '../doc_alias/type.Typedef.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Trait', + 'alias': 'TraitItem', + 'href': '../doc_alias/trait.Trait.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'Target', + 'alias': 'TraitTypeItem', + 'href': '../doc_alias/trait.Trait.html#associatedtype.Target' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'AssociatedConst', + 'alias': 'AssociatedConstItem', + 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'function', + 'alias': 'TraitFunctionItem', + 'href': '../doc_alias/trait.Trait.html#tymethod.function' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'function', + 'alias': 'FunctionItem', + 'href': '../doc_alias/fn.function.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Module', + 'alias': 'ModuleItem', + 'href': '../doc_alias/Module/index.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Const', + 'alias': 'ConstItem', + 'href': '../doc_alias/constant.Const.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Static', + 'alias': 'StaticItem', + 'href': '../doc_alias/static.Static.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Union', + 'alias': 'UnionItem', + 'href': '../doc_alias/union.Union.html' + }, + // Not an alias! + { + 'path': 'doc_alias::Union', + 'name': 'union_item', + 'href': '../doc_alias/union.Union.html#structfield.union_item' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Union', + 'name': 'union_item', + 'alias': 'UnionFieldItem', + 'href': '../doc_alias/union.Union.html#structfield.union_item' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Union', + 'name': 'method', + 'alias': 'UnionMethodItem', + 'href': '../doc_alias/union.Union.html#method.method' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Macro', + 'alias': 'MacroItem', + 'href': '../doc_alias/macro.Macro.html' + }, + ], + }, +]; diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs new file mode 100644 index 0000000000000..8cd0a82997414 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias.rs @@ -0,0 +1,80 @@ +#![feature(doc_alias)] + +#[doc(alias = "StructItem")] +pub struct Struct { + #[doc(alias = "StructFieldItem")] + pub field: u32, +} + +impl Struct { + #[doc(alias = "StructMethodItem")] + pub fn method(&self) {} +} + +impl Trait for Struct { + // Shouldn't be listed in aliases! + #[doc(alias = "ImplTraitItem")] + type Target = u32; + // Shouldn't be listed in aliases! + #[doc(alias = "ImplAssociatedConstItem")] + const AssociatedConst: i32 = 12; + + // Shouldn't be listed in aliases! + #[doc(alias = "ImplTraitFunction")] + fn function() -> Self::Target { 0 } +} + +#[doc(alias = "EnumItem")] +pub enum Enum { + #[doc(alias = "VariantItem")] + Variant, +} + +impl Enum { + #[doc(alias = "EnumMethodItem")] + pub fn method(&self) {} +} + +#[doc(alias = "TypedefItem")] +pub type Typedef = i32; + +#[doc(alias = "TraitItem")] +pub trait Trait { + #[doc(alias = "TraitTypeItem")] + type Target; + #[doc(alias = "AssociatedConstItem")] + const AssociatedConst: i32; + + #[doc(alias = "TraitFunctionItem")] + fn function() -> Self::Target; +} + +#[doc(alias = "FunctionItem")] +pub fn function() {} + +#[doc(alias = "ModuleItem")] +pub mod Module {} + +#[doc(alias = "ConstItem")] +pub const Const: u32 = 0; + +#[doc(alias = "StaticItem")] +pub static Static: u32 = 0; + +#[doc(alias = "UnionItem")] +pub union Union { + #[doc(alias = "UnionFieldItem")] + pub union_item: u32, + pub y: f32, +} + +impl Union { + #[doc(alias = "UnionMethodItem")] + pub fn method(&self) {} +} + +#[doc(alias = "MacroItem")] +#[macro_export] +macro_rules! Macro { + () => {} +} From 9697c467aca28f40d8ef7c59b9f5bc670c1b85f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:43:55 +0200 Subject: [PATCH 05/17] Update std tests --- src/test/rustdoc-js-std/alias-2.js | 4 +++- src/test/rustdoc-js-std/alias.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index f3c6713692b59..0ce1b87b76153 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -4,7 +4,9 @@ const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'std::ops', 'name': 'AddAssign' }, + { 'path': 'core', 'name': 'AddAssign' }, + { 'path': 'core', 'name': 'Add' }, + { 'path': 'std', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js-std/alias.js b/src/test/rustdoc-js-std/alias.js index 2b709c99119ae..0b1e983117f2f 100644 --- a/src/test/rustdoc-js-std/alias.js +++ b/src/test/rustdoc-js-std/alias.js @@ -5,7 +5,7 @@ const QUERY = '['; const EXPECTED = { 'others': [ { 'path': 'std', 'name': 'slice' }, - { 'path': 'std::ops', 'name': 'IndexMut' }, - { 'path': 'std::ops', 'name': 'Index' }, + { 'path': 'std', 'name': 'IndexMut' }, + { 'path': 'std', 'name': 'Index' }, ], }; From f581cf754492f9f122193b8d8a7750ab38a87485 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 14:51:06 +0200 Subject: [PATCH 06/17] Merge aliases and search-index --- src/librustdoc/html/layout.rs | 1 - src/librustdoc/html/render.rs | 36 -------- src/librustdoc/html/render/cache.rs | 44 +++++----- src/librustdoc/html/static/main.js | 126 +++++++++++++++++++--------- src/test/rustdoc-js-std/alias-2.js | 6 +- src/test/rustdoc-js-std/alias.js | 4 +- src/tools/rustdoc-js/tester.js | 9 +- 7 files changed, 118 insertions(+), 108 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 0922c8cdd1200..ea65b3905272e 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -114,7 +114,6 @@ pub fn render( window.rootPath = \"{root_path}\";\ window.currentCrate = \"{krate}\";\ \ - \ \ {static_extra_scripts}\ {extra_scripts}\ diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4ed367a5c80d3..9454baf764097 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -825,42 +825,6 @@ themePicker.onblur = handleThemeButtonsBlur; Ok((ret, krates)) } - fn show_item(item: &IndexItem, krate: &str) -> String { - format!( - "{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}", - krate, - item.ty as usize, - item.name, - item.desc.replace("'", "\\'"), - item.path, - if let Some(p) = item.parent_idx { format!(",'parent':{}", p) } else { String::new() } - ) - } - - let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix)); - { - let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); - let mut output = String::with_capacity(100); - for (alias, items) in cx.cache.get_aliases() { - if items.is_empty() { - continue; - } - output.push_str(&format!( - "\"{}\":[{}],", - alias, - items.iter().map(|v| show_item(v, &krate.name)).collect::>().join(",") - )); - } - all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output)); - all_aliases.sort(); - let mut v = Buffer::html(); - writeln!(&mut v, "var ALIASES = {{}};"); - for aliases in &all_aliases { - writeln!(&mut v, "{}", aliases); - } - cx.shared.fs.write(&dst, v.into_inner().into_bytes())?; - } - use std::ffi::OsString; #[derive(Debug)] diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 17003334bc856..53cf1abb16d56 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -503,27 +503,6 @@ impl DocFolder for Cache { } } -impl Cache { - pub fn get_aliases<'a>(&'a self) -> FxHashMap> { - self.aliases - .iter() - .map(|(k, values)| { - ( - k.clone(), - values - .iter() - .filter(|v| { - let x = &self.search_index[**v]; - x.parent_idx.is_some() == x.parent.is_some() - }) - .map(|v| &self.search_index[*v]) - .collect::>(), - ) - }) - .collect() - } -} - /// Attempts to find where an external crate is located, given that we're /// rendering in to the specified source destination. fn extern_location( @@ -640,6 +619,23 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); + let crate_aliases = aliases + .iter() + .map(|(k, values)| { + ( + k.clone(), + values + .iter() + .filter_map(|v| { + let x = &crate_items[*v]; + if x.parent_idx.is_some() == x.parent.is_some() { Some(*v) } else { None } + }) + .collect::>(), + ) + }) + .filter(|(_, values)| !values.is_empty()) + .collect::>(); + #[derive(Serialize)] struct CrateData<'a> { doc: String, @@ -647,6 +643,11 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { items: Vec<&'a IndexItem>, #[serde(rename = "p")] paths: Vec<(ItemType, String)>, + // The String is alias name and the vec is the list of the elements with this alias. + // + // To be noted: the `usize` elements are indexes to `items`. + #[serde(rename = "a")] + aliases: Option)>>, } // Collect the index into a string @@ -657,6 +658,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { doc: crate_doc, items: crate_items, paths: crate_paths, + aliases: if crate_aliases.is_empty() { None } else { Some(crate_aliases) }, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 411d2d44059b2..94ae69fde57fd 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -531,6 +531,7 @@ function getSearchElement() { var OUTPUT_DATA = 1; var NO_TYPE_FILTER = -1; var currentResults, index, searchIndex; + var ALIASES = {}; var params = getQueryStringParams(); // Populate search bar with query string search term when provided, @@ -963,46 +964,60 @@ function getSearchElement() { return itemTypes[ty.ty] + ty.path + ty.name; } + function createAliasFromItem(item) { + return { + crate: item.crate, + name: item.name, + path: item.path, + desc: item.desc, + ty: item.ty, + parent: item.parent, + type: item.parent, + is_alias: true, + }; + } + function handleAliases(ret, query, filterCrates) { - if (ALIASES) { - var aliases = []; - if (filterCrates !== undefined && - ALIASES[filterCrates] && - ALIASES[filterCrates][query.search]) { - aliases = ALIASES[filterCrates][query.search]; - } else { - Object.keys(ALIASES).forEach(function(crate) { - if (ALIASES[crate][query.search]) { - for (var i = 0; i < ALIASES[crate][query.search].length; ++i) { - aliases.push(ALIASES[crate][query.search][i]); - } - } - }); + var aliases = []; + var i; + if (filterCrates !== undefined && + ALIASES[filterCrates] && + ALIASES[filterCrates][query.search]) { + for (i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push( + createAliasFromItem(searchIndex[ALIASES[filterCrates][query.search]])); } - aliases.sort(function(aaa, bbb) { - if (aaa.path < bbb.path) { - return 1; - } else if (aaa.path === bbb.path) { - return 0; + } else { + Object.keys(ALIASES).forEach(function(crate) { + if (ALIASES[crate][query.search]) { + for (i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push( + createAliasFromItem( + searchIndex[ALIASES[crate][query.search][i]])); + } } - return -1; }); - for (var i = 0; i < aliases.length; ++i) { - var alias = aliases[i]; - alias.is_alias = true; - if (typeof alias.parent === "number") { - alias.parent = rawSearchIndex[alias.crate].p[alias.parent]; - } - alias.alias = query.raw; - alias.path = alias.p || alias.crate; - var res = buildHrefAndPath(aliases[i]); - alias.displayPath = pathSplitter(res[0]); - alias.fullPath = alias.displayPath + alias.name; - alias.href = res[1]; - ret.others.unshift(alias); - if (ret.others.length > MAX_RESULTS) { - ret.others.pop(); - } + } + aliases.sort(function(aaa, bbb) { + if (aaa.path < bbb.path) { + return 1; + } else if (aaa.path === bbb.path) { + return 0; + } + return -1; + }); + for (i = 0; i < aliases.length; ++i) { + var alias = aliases[i]; + + alias.alias = query.raw; + var res = buildHrefAndPath(alias); + alias.displayPath = pathSplitter(res[0]); + alias.fullPath = alias.displayPath + alias.name; + alias.href = res[1]; + + ret.others.unshift(alias); + if (ret.others.length > MAX_RESULTS) { + ret.others.pop(); } } } @@ -1683,10 +1698,13 @@ function getSearchElement() { searchIndex = []; var searchWords = []; var i; + var currentIndex = 0; for (var crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } + var crateSize = 0; + searchWords.push(crate); searchIndex.push({ crate: crate, @@ -1696,6 +1714,7 @@ function getSearchElement() { desc: rawSearchIndex[crate].doc, type: null, }); + currentIndex += 1; // an array of [(Number) item type, // (String) name, @@ -1707,6 +1726,9 @@ function getSearchElement() { // an array of [(Number) item type, // (String) name] var paths = rawSearchIndex[crate].p; + // a array of [(String) alias name + // [Number] index to items] + var aliases = rawSearchIndex[crate].a; // convert `rawPaths` entries into object form var len = paths.length; @@ -1725,9 +1747,18 @@ function getSearchElement() { var lastPath = ""; for (i = 0; i < len; ++i) { var rawRow = items[i]; - var row = {crate: crate, ty: rawRow[0], name: rawRow[1], - path: rawRow[2] || lastPath, desc: rawRow[3], - parent: paths[rawRow[4]], type: rawRow[5]}; + if (!rawRow[2]) { + rawRow[2] = lastPath; + } + var row = { + crate: crate, + ty: rawRow[0], + name: rawRow[1], + path: rawRow[2], + desc: rawRow[3], + parent: paths[rawRow[4]], + type: rawRow[5], + }; searchIndex.push(row); if (typeof row.name === "string") { var word = row.name.toLowerCase(); @@ -1736,7 +1767,24 @@ function getSearchElement() { searchWords.push(""); } lastPath = row.path; + crateSize += 1; + } + + if (aliases) { + ALIASES[crate] = {}; + var j, local_aliases; + for (i = 0; i < aliases.length; ++i) { + var alias_name = aliases[i][0]; + if (!ALIASES[crate].hasOwnProperty(alias_name)) { + ALIASES[crate][alias_name] = []; + } + local_aliases = aliases[i][1]; + for (j = 0; j < local_aliases.length; ++j) { + ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex); + } + } } + currentIndex += crateSize; } return searchWords; } diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index 0ce1b87b76153..cb6ec4f8fed4e 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -4,9 +4,9 @@ const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'core', 'name': 'AddAssign' }, - { 'path': 'core', 'name': 'Add' }, - { 'path': 'std', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'Add' }, + { 'path': 'std::ops', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js-std/alias.js b/src/test/rustdoc-js-std/alias.js index 0b1e983117f2f..2b709c99119ae 100644 --- a/src/test/rustdoc-js-std/alias.js +++ b/src/test/rustdoc-js-std/alias.js @@ -5,7 +5,7 @@ const QUERY = '['; const EXPECTED = { 'others': [ { 'path': 'std', 'name': 'slice' }, - { 'path': 'std', 'name': 'IndexMut' }, - { 'path': 'std', 'name': 'Index' }, + { 'path': 'std::ops', 'name': 'IndexMut' }, + { 'path': 'std::ops', 'name': 'Index' }, ], }; diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 72bc496c5b5d3..90315d6f64431 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -218,7 +218,7 @@ function lookForEntry(entry, data) { return null; } -function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { +function loadMainJsAndIndex(mainJs, searchIndex, crate) { if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -238,17 +238,15 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch"]; + ALIASES = {}; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; - finalJS += aliases; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); var index = loaded.buildIndex(searchIndex.rawSearchIndex); - // We make it "global" so that the "loaded.execSearch" function will find it. - rawSearchIndex = searchIndex.rawSearchIndex; return [loaded, index]; } @@ -340,11 +338,10 @@ function runChecks(testFile, loaded, index) { function load_files(doc_folder, resource_suffix, crate) { var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); - var aliases = readFile(path.join(doc_folder, "aliases" + resource_suffix + ".js")); var searchIndex = readFile( path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); - return loadMainJsAndIndex(mainJs, aliases, searchIndex, crate); + return loadMainJsAndIndex(mainJs, searchIndex, crate); } function showHelp() { From ce915f500a1743945c5bc67d133d6801dbf9b87f Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 13 May 2020 18:31:33 -0400 Subject: [PATCH 07/17] remove extra space from crate-level doctest names --- src/librustdoc/test.rs | 6 +++++- src/test/rustdoc-ui/doctest-output.rs | 15 +++++++++++++++ src/test/rustdoc-ui/doctest-output.stdout | 7 +++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/doctest-output.rs create mode 100644 src/test/rustdoc-ui/doctest-output.stdout diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index a00c9a0bcea65..5d6ec5f09d9d3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -676,7 +676,11 @@ impl Collector { } fn generate_name(&self, line: usize, filename: &FileName) -> String { - format!("{} - {} (line {})", filename, self.names.join("::"), line) + let mut item_path = self.names.join("::"); + if !item_path.is_empty() { + item_path.push(' '); + } + format!("{} - {}(line {})", filename, item_path, line) } pub fn set_position(&mut self, position: Span) { diff --git a/src/test/rustdoc-ui/doctest-output.rs b/src/test/rustdoc-ui/doctest-output.rs new file mode 100644 index 0000000000000..b34cb0afd5271 --- /dev/null +++ b/src/test/rustdoc-ui/doctest-output.rs @@ -0,0 +1,15 @@ +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// check-pass + +//! ``` +//! assert_eq!(1 + 1, 2); +//! ``` + +pub mod foo { + + /// ``` + /// assert_eq!(1 + 1, 2); + /// ``` + pub fn bar() {} +} diff --git a/src/test/rustdoc-ui/doctest-output.stdout b/src/test/rustdoc-ui/doctest-output.stdout new file mode 100644 index 0000000000000..9a55bf5019692 --- /dev/null +++ b/src/test/rustdoc-ui/doctest-output.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test $DIR/doctest-output.rs - (line 5) ... ok +test $DIR/doctest-output.rs - foo::bar (line 11) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + From 883c177abb216fcef5b2d2369970394b0967f302 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 15:26:17 +0200 Subject: [PATCH 08/17] Move doc alias discovery into the Attributes struct and some code improvements --- src/librustdoc/clean/types.rs | 9 +++++++ src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/render/cache.rs | 41 +++-------------------------- src/librustdoc/html/static/main.js | 2 +- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 0a682857b1825..cd767802714b0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -643,6 +643,15 @@ impl Attributes { }) .collect() } + + pub fn get_doc_aliases(&self) -> FxHashSet { + self.other_attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + } } impl PartialEq for Attributes { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9454baf764097..abca8ab778cc3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -278,7 +278,7 @@ pub struct RenderInfo { /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] -pub struct IndexItem { +struct IndexItem { ty: ItemType, name: String, path: String, diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 53cf1abb16d56..b8d97c2ac503b 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -328,15 +328,7 @@ impl DocFolder for Cache { search_type: get_index_search_type(&item), }); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { + for alias in item.attrs.get_doc_aliases() { self.aliases .entry(alias.to_lowercase()) .or_insert(Vec::with_capacity(1)) @@ -378,9 +370,6 @@ impl DocFolder for Cache { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) - | clean::StructFieldItem(..) - | clean::TyMethodItem(..) - | clean::MethodItem(..) if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice @@ -564,15 +553,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { + for alias in item.attrs.get_doc_aliases().into_iter() { aliases .entry(alias.to_lowercase()) .or_insert(Vec::with_capacity(1)) @@ -619,22 +600,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); - let crate_aliases = aliases - .iter() - .map(|(k, values)| { - ( - k.clone(), - values - .iter() - .filter_map(|v| { - let x = &crate_items[*v]; - if x.parent_idx.is_some() == x.parent.is_some() { Some(*v) } else { None } - }) - .collect::>(), - ) - }) - .filter(|(_, values)| !values.is_empty()) - .collect::>(); + let crate_aliases = + aliases.iter().map(|(k, values)| (k.clone(), values.clone())).collect::>(); #[derive(Serialize)] struct CrateData<'a> { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 94ae69fde57fd..22e312e13c011 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -972,7 +972,7 @@ function getSearchElement() { desc: item.desc, ty: item.ty, parent: item.parent, - type: item.parent, + type: item.type, is_alias: true, }; } From c4d9318be6a493da4c6aa307dd4de7e24a15120a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 May 2020 21:42:41 +0200 Subject: [PATCH 09/17] Make current crate aliases go first --- src/librustdoc/html/static/main.js | 20 ++++++--- src/test/rustdoc-js-std/alias-2.js | 6 +-- src/test/rustdoc-js/doc-alias.js | 68 +++++++++++++++++++++--------- src/test/rustdoc-js/doc-alias.rs | 1 - src/tools/rustdoc-js/tester.js | 6 ++- 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 22e312e13c011..7592331dd656d 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -978,7 +978,10 @@ function getSearchElement() { } function handleAliases(ret, query, filterCrates) { + // We separate aliases and crate aliases because we want to have current crate + // aliases to be before the others in the displayed results. var aliases = []; + var crateAliases = []; var i; if (filterCrates !== undefined && ALIASES[filterCrates] && @@ -990,25 +993,28 @@ function getSearchElement() { } else { Object.keys(ALIASES).forEach(function(crate) { if (ALIASES[crate][query.search]) { + var pushTo = crate === window.currentCrate ? crateAliases : aliases; for (i = 0; i < ALIASES[crate][query.search].length; ++i) { - aliases.push( + pushTo.push( createAliasFromItem( searchIndex[ALIASES[crate][query.search][i]])); } } }); } - aliases.sort(function(aaa, bbb) { + + var sortFunc = function(aaa, bbb) { if (aaa.path < bbb.path) { return 1; } else if (aaa.path === bbb.path) { return 0; } return -1; - }); - for (i = 0; i < aliases.length; ++i) { - var alias = aliases[i]; + }; + crateAliases.sort(sortFunc); + aliases.sort(sortFunc); + var pushFunc = function(alias) { alias.alias = query.raw; var res = buildHrefAndPath(alias); alias.displayPath = pathSplitter(res[0]); @@ -1019,7 +1025,9 @@ function getSearchElement() { if (ret.others.length > MAX_RESULTS) { ret.others.pop(); } - } + }; + onEach(aliases, pushFunc); + onEach(crateAliases, pushFunc); } // quoted values mean literal search diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index cb6ec4f8fed4e..798fa29efbd2d 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -1,12 +1,10 @@ -// ignore-order - const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'core::ops', 'name': 'AddAssign' }, - { 'path': 'core::ops', 'name': 'Add' }, { 'path': 'std::ops', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, + { 'path': 'core::ops', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js index e6310b625e533..896808d415780 100644 --- a/src/test/rustdoc-js/doc-alias.js +++ b/src/test/rustdoc-js/doc-alias.js @@ -32,7 +32,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Struct', 'alias': 'StructItem', - 'href': '../doc_alias/struct.Struct.html' + 'href': '../doc_alias/struct.Struct.html', + 'is_alias': true }, ], }, @@ -42,7 +43,8 @@ const EXPECTED = [ 'path': 'doc_alias::Struct', 'name': 'field', 'alias': 'StructFieldItem', - 'href': '../doc_alias/struct.Struct.html#structfield.field' + 'href': '../doc_alias/struct.Struct.html#structfield.field', + 'is_alias': true }, ], }, @@ -52,7 +54,8 @@ const EXPECTED = [ 'path': 'doc_alias::Struct', 'name': 'method', 'alias': 'StructMethodItem', - 'href': '../doc_alias/struct.Struct.html#method.method' + 'href': '../doc_alias/struct.Struct.html#method.method', + 'is_alias': true }, ], }, @@ -65,8 +68,15 @@ const EXPECTED = [ 'others': [], }, { - // ImplTraitFunction - 'others': [], + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'function', + 'alias': 'ImplTraitFunction', + 'href': '../doc_alias/struct.Struct.html#method.function', + 'is_alias': true + }, + ], }, { 'others': [ @@ -74,7 +84,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Enum', 'alias': 'EnumItem', - 'href': '../doc_alias/enum.Enum.html' + 'href': '../doc_alias/enum.Enum.html', + 'is_alias': true }, ], }, @@ -84,7 +95,8 @@ const EXPECTED = [ 'path': 'doc_alias::Enum', 'name': 'Variant', 'alias': 'VariantItem', - 'href': '../doc_alias/enum.Enum.html#variant.Variant' + 'href': '../doc_alias/enum.Enum.html#variant.Variant', + 'is_alias': true }, ], }, @@ -94,7 +106,8 @@ const EXPECTED = [ 'path': 'doc_alias::Enum', 'name': 'method', 'alias': 'EnumMethodItem', - 'href': '../doc_alias/enum.Enum.html#method.method' + 'href': '../doc_alias/enum.Enum.html#method.method', + 'is_alias': true }, ], }, @@ -104,7 +117,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Typedef', 'alias': 'TypedefItem', - 'href': '../doc_alias/type.Typedef.html' + 'href': '../doc_alias/type.Typedef.html', + 'is_alias': true }, ], }, @@ -114,7 +128,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Trait', 'alias': 'TraitItem', - 'href': '../doc_alias/trait.Trait.html' + 'href': '../doc_alias/trait.Trait.html', + 'is_alias': true }, ], }, @@ -124,7 +139,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'Target', 'alias': 'TraitTypeItem', - 'href': '../doc_alias/trait.Trait.html#associatedtype.Target' + 'href': '../doc_alias/trait.Trait.html#associatedtype.Target', + 'is_alias': true }, ], }, @@ -134,7 +150,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'AssociatedConst', 'alias': 'AssociatedConstItem', - 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst' + 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst', + 'is_alias': true }, ], }, @@ -144,7 +161,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'function', 'alias': 'TraitFunctionItem', - 'href': '../doc_alias/trait.Trait.html#tymethod.function' + 'href': '../doc_alias/trait.Trait.html#tymethod.function', + 'is_alias': true }, ], }, @@ -154,7 +172,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'function', 'alias': 'FunctionItem', - 'href': '../doc_alias/fn.function.html' + 'href': '../doc_alias/fn.function.html', + 'is_alias': true }, ], }, @@ -164,7 +183,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Module', 'alias': 'ModuleItem', - 'href': '../doc_alias/Module/index.html' + 'href': '../doc_alias/Module/index.html', + 'is_alias': true }, ], }, @@ -174,7 +194,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Const', 'alias': 'ConstItem', - 'href': '../doc_alias/constant.Const.html' + 'href': '../doc_alias/constant.Const.html', + 'is_alias': true }, ], }, @@ -184,7 +205,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Static', 'alias': 'StaticItem', - 'href': '../doc_alias/static.Static.html' + 'href': '../doc_alias/static.Static.html', + 'is_alias': true }, ], }, @@ -194,7 +216,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Union', 'alias': 'UnionItem', - 'href': '../doc_alias/union.Union.html' + 'href': '../doc_alias/union.Union.html', + 'is_alias': true }, // Not an alias! { @@ -210,7 +233,8 @@ const EXPECTED = [ 'path': 'doc_alias::Union', 'name': 'union_item', 'alias': 'UnionFieldItem', - 'href': '../doc_alias/union.Union.html#structfield.union_item' + 'href': '../doc_alias/union.Union.html#structfield.union_item', + 'is_alias': true }, ], }, @@ -220,7 +244,8 @@ const EXPECTED = [ 'path': 'doc_alias::Union', 'name': 'method', 'alias': 'UnionMethodItem', - 'href': '../doc_alias/union.Union.html#method.method' + 'href': '../doc_alias/union.Union.html#method.method', + 'is_alias': true }, ], }, @@ -230,7 +255,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Macro', 'alias': 'MacroItem', - 'href': '../doc_alias/macro.Macro.html' + 'href': '../doc_alias/macro.Macro.html', + 'is_alias': true }, ], }, diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs index 8cd0a82997414..84c638a199507 100644 --- a/src/test/rustdoc-js/doc-alias.rs +++ b/src/test/rustdoc-js/doc-alias.rs @@ -19,7 +19,6 @@ impl Trait for Struct { #[doc(alias = "ImplAssociatedConstItem")] const AssociatedConst: i32 = 12; - // Shouldn't be listed in aliases! #[doc(alias = "ImplTraitFunction")] fn function() -> Self::Target { 0 } } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 90315d6f64431..1fa46ce99f5e6 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -218,7 +218,7 @@ function lookForEntry(entry, data) { return null; } -function loadMainJsAndIndex(mainJs, searchIndex, crate) { +function loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate) { if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -241,6 +241,7 @@ function loadMainJsAndIndex(mainJs, searchIndex, crate) { ALIASES = {}; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; + finalJS += loadThings(["onEach"], 'function', extractFunction, storageJs); finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); @@ -338,10 +339,11 @@ function runChecks(testFile, loaded, index) { function load_files(doc_folder, resource_suffix, crate) { var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); + var storageJs = readFile(path.join(doc_folder, "storage" + resource_suffix + ".js")); var searchIndex = readFile( path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); - return loadMainJsAndIndex(mainJs, searchIndex, crate); + return loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate); } function showHelp() { From e17ac668997410a1a9d2da8725329afb8b5f2901 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 May 2020 17:03:37 +0200 Subject: [PATCH 10/17] * Update aliases data struct from HashMap to BTreeMap to have more deterministic results * Update Javascript to take this change into account * Update CrateData::aliases field to take a reference instead (it allowed to remove a conversion loop) --- src/librustdoc/html/render/cache.rs | 16 +++++++--------- src/librustdoc/html/static/main.js | 7 ++++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index b8d97c2ac503b..57d385de32096 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -120,7 +120,7 @@ crate struct Cache { /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. - pub(super) aliases: FxHashMap>, + pub(super) aliases: BTreeMap>, } impl Cache { @@ -331,7 +331,7 @@ impl DocFolder for Cache { for alias in item.attrs.get_doc_aliases() { self.aliases .entry(alias.to_lowercase()) - .or_insert(Vec::with_capacity(1)) + .or_insert(Vec::new()) .push(self.search_index.len() - 1); } } @@ -553,10 +553,10 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); - for alias in item.attrs.get_doc_aliases().into_iter() { + for alias in item.attrs.get_doc_aliases() { aliases .entry(alias.to_lowercase()) - .or_insert(Vec::with_capacity(1)) + .or_insert(Vec::new()) .push(search_index.len() - 1); } } @@ -600,9 +600,6 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); - let crate_aliases = - aliases.iter().map(|(k, values)| (k.clone(), values.clone())).collect::>(); - #[derive(Serialize)] struct CrateData<'a> { doc: String, @@ -614,7 +611,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { // // To be noted: the `usize` elements are indexes to `items`. #[serde(rename = "a")] - aliases: Option)>>, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + aliases: &'a BTreeMap>, } // Collect the index into a string @@ -625,7 +623,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { doc: crate_doc, items: crate_items, paths: crate_paths, - aliases: if crate_aliases.is_empty() { None } else { Some(crate_aliases) }, + aliases, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 7592331dd656d..9b498d66249e2 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1781,12 +1781,13 @@ function getSearchElement() { if (aliases) { ALIASES[crate] = {}; var j, local_aliases; - for (i = 0; i < aliases.length; ++i) { - var alias_name = aliases[i][0]; + for (var alias_name in aliases) { + if (!aliases.hasOwnProperty(alias_name)) { continue; } + if (!ALIASES[crate].hasOwnProperty(alias_name)) { ALIASES[crate][alias_name] = []; } - local_aliases = aliases[i][1]; + local_aliases = aliases[alias_name]; for (j = 0; j < local_aliases.length; ++j) { ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex); } From 89543793126b142b8c40b4cc83e284a91cccb499 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 May 2020 23:29:50 +0200 Subject: [PATCH 11/17] make sure even unleashed miri does not do pointer stuff --- .../ui/consts/miri_unleashed/ptr_arith.rs | 29 ++++++++++++++ .../ui/consts/miri_unleashed/ptr_arith.stderr | 39 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/test/ui/consts/miri_unleashed/ptr_arith.rs create mode 100644 src/test/ui/consts/miri_unleashed/ptr_arith.stderr diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs new file mode 100644 index 0000000000000..81985f9f625a5 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs @@ -0,0 +1,29 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(core_intrinsics)] +#![allow(const_err)] + +// A test demonstrating that we prevent doing even trivial +// pointer arithmetic or comparison during CTFE. + +static CMP: () = { + let x = &0 as *const _; + let _v = x == x; + //~^ ERROR could not evaluate static initializer + //~| NOTE pointer arithmetic or comparison +}; + +static INT_PTR_ARITH: () = unsafe { + let x: usize = std::mem::transmute(&0); + let _v = x + 0; + //~^ ERROR could not evaluate static initializer + //~| NOTE pointer-to-integer cast +}; + +static PTR_ARITH: () = unsafe { + let x = &0 as *const _; + let _v = core::intrinsics::offset(x, 0); + //~^ ERROR could not evaluate static initializer + //~| NOTE calling intrinsic `offset` +}; + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr new file mode 100644 index 0000000000000..5bd534a16b863 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -0,0 +1,39 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:10:14 + | +LL | let _v = x == x; + | ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:17:14 + | +LL | let _v = x + 0; + | ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:24:14 + | +LL | let _v = core::intrinsics::offset(x, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "calling intrinsic `offset`" needs an rfc before being allowed inside constants + +warning: skipping const checks + | +help: skipping check for `const_compare_raw_pointers` feature + --> $DIR/ptr_arith.rs:10:14 + | +LL | let _v = x == x; + | ^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:16:20 + | +LL | let x: usize = std::mem::transmute(&0); + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:24:14 + | +LL | let _v = core::intrinsics::offset(x, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. From e84b379351577cae8cc3e89bf66c71bcabf547d7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 23 Apr 2020 17:09:21 -0400 Subject: [PATCH 12/17] [const-prop] Don't replace Rvalues that are already constants --- src/librustc_mir/transform/const_prop.rs | 7 +++++++ .../const_prop/mutable_variable/rustc.main.ConstProp.diff | 3 +-- .../mutable_variable_aggregate/rustc.main.ConstProp.diff | 3 +-- .../rustc.arg_src.CopyPropagation.diff | 2 +- .../copy_propagation_arg/rustc.bar.CopyPropagation.diff | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index e898f22ec230d..bdf2193c6af45 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -616,6 +616,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { value: OpTy<'tcx>, source_info: SourceInfo, ) { + if let Rvalue::Use(Operand::Constant(c)) = rval { + if !matches!(c.literal.val, ConstKind::Unevaluated(..)) { + trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c); + return; + } + } + trace!("attepting to replace {:?} with {:?}", rval, value); if let Err(e) = self.ecx.const_validate_operand( value, diff --git a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff index c6c5b0cf72635..187c17454350a 100644 --- a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff @@ -26,8 +26,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant -- // + span: $DIR/mutable_variable.rs:6:9: 6:11 -+ // + span: $DIR/mutable_variable.rs:6:5: 6:11 + // + span: $DIR/mutable_variable.rs:6:9: 6:11 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff index 26f0250d94c0b..cf432b2acc1c5 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff @@ -34,8 +34,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate.rs:6:11: 6:13 -+ // + span: $DIR/mutable_variable_aggregate.rs:6:5: 6:13 + // + span: $DIR/mutable_variable_aggregate.rs:6:11: 6:13 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff index b976449ca6d32..1e0271a560f65 100644 --- a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff @@ -17,7 +17,7 @@ // + ty: i32 // + val: Value(Scalar(0x0000007b)) // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:29:5: 29:12 + // + span: $DIR/copy_propagation_arg.rs:29:9: 29:12 // + literal: Const { ty: i32, val: Value(Scalar(0x0000007b)) } _0 = _2; // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6 StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2 diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff index 26f8068f674ef..b875bbea67bdf 100644 --- a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff @@ -28,7 +28,7 @@ // + ty: u8 // + val: Value(Scalar(0x05)) // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10 + // + span: $DIR/copy_propagation_arg.rs:17:9: 17:10 // + literal: Const { ty: u8, val: Value(Scalar(0x05)) } _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:15:19: 18:2 // ty::Const From 257e3772cb1b434a3c3fc8ac61ef808929036558 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 15 May 2020 04:49:23 +0000 Subject: [PATCH 13/17] doc: add links to rotate_(left|right) --- src/libcore/num/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a259e293b0c1a..9039e71b82864 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1448,8 +1448,8 @@ any high-order bits of `rhs` that would cause the shift to exceed the bitwidth o Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. -The primitive integer types all implement a `rotate_left` function, which may be what you want -instead. +The primitive integer types all implement a `[`rotate_left`](#method.rotate_left) function, +which may be what you want instead. # Examples @@ -1480,8 +1480,8 @@ removes any high-order bits of `rhs` that would cause the shift to exceed the bi Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other -end. The primitive integer types all implement a `rotate_right` function, which may be what you want -instead. +end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function, +which may be what you want instead. # Examples @@ -3508,8 +3508,8 @@ Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. The primitive integer -types all implement a `rotate_left` function, which may -be what you want instead. +types all implement a [`rotate_left`](#method.rotate_left) function, +which may be what you want instead. # Examples @@ -3542,8 +3542,8 @@ Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. The primitive integer -types all implement a `rotate_right` function, which may -be what you want instead. +types all implement a [`rotate_right`](#method.rotate_right) function, +which may be what you want instead. # Examples From 00268be9da13215398d779b2e344ffa3e300693c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Thu, 14 May 2020 22:06:44 +0100 Subject: [PATCH 14/17] Remove lang_items\(\).*\.unwrap\(\) --- src/librustc_mir/monomorphize/mod.rs | 4 +++- .../hair/pattern/const_to_pat.rs | 3 ++- .../traits/structural_match.rs | 5 +++-- src/librustc_typeck/check/closure.rs | 6 +++--- src/librustc_typeck/check/demand.rs | 8 ++++---- src/librustc_typeck/check/mod.rs | 16 ++++++++-------- src/librustc_typeck/coherence/builtin.rs | 19 +++++++++++-------- 7 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 98a3d9584f587..28edd87a3add5 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -2,6 +2,8 @@ use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_hir::lang_items::CoerceUnsizedTraitLangItem; + pub mod collector; pub mod partitioning; @@ -10,7 +12,7 @@ pub fn custom_coerce_unsize_info<'tcx>( source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { - let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); + let def_id = tcx.require_lang_item(CoerceUnsizedTraitLangItem, None); let trait_ref = ty::Binder::bind(ty::TraitRef { def_id, diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index d3129751586af..28ec2ca13d5af 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -141,7 +141,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // code at the moment, because types like `for <'a> fn(&'a ())` do // not *yet* implement `PartialEq`. So for now we leave this here. let ty_is_partial_eq: bool = { - let partial_eq_trait_id = self.tcx().require_lang_item(EqTraitLangItem, None); + let partial_eq_trait_id = + self.tcx().require_lang_item(EqTraitLangItem, Some(self.span)); let obligation: PredicateObligation<'_> = predicate_for_trait_def( self.tcx(), self.param_env, diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs index 8007290f35d85..eb63505b69b41 100644 --- a/src/librustc_trait_selection/traits/structural_match.rs +++ b/src/librustc_trait_selection/traits/structural_match.rs @@ -4,6 +4,7 @@ use crate::traits::{self, ConstPatternStructural, TraitEngine}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_hir::lang_items::{StructuralPeqTraitLangItem, StructuralTeqTraitLangItem}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::Span; @@ -69,7 +70,7 @@ pub fn type_marked_structural( let mut fulfillment_cx = traits::FulfillmentContext::new(); let cause = ObligationCause::new(span, id, ConstPatternStructural); // require `#[derive(PartialEq)]` - let structural_peq_def_id = infcx.tcx.lang_items().structural_peq_trait().unwrap(); + let structural_peq_def_id = infcx.tcx.require_lang_item(StructuralPeqTraitLangItem, Some(span)); fulfillment_cx.register_bound( infcx, ty::ParamEnv::empty(), @@ -80,7 +81,7 @@ pub fn type_marked_structural( // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.) let cause = ObligationCause::new(span, id, ConstPatternStructural); - let structural_teq_def_id = infcx.tcx.lang_items().structural_teq_trait().unwrap(); + let structural_teq_def_id = infcx.tcx.require_lang_item(StructuralTeqTraitLangItem, Some(span)); fulfillment_cx.register_bound( infcx, ty::ParamEnv::empty(), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 035e5880dc522..87a6f119acb09 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -6,7 +6,7 @@ use crate::astconv::AstConv; use crate::middle::region; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items; +use rustc_hir::lang_items::{FutureTraitLangItem, GeneratorTraitLangItem}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; @@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some(); - let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem, cause_span); + let gen_trait = tcx.require_lang_item(GeneratorTraitLangItem, cause_span); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator"); @@ -678,7 +678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check that this is a projection from the `Future` trait. let trait_ref = predicate.projection_ty.trait_ref(self.tcx); - let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(cause_span)); if trait_ref.def_id != future_trait { debug!("deduce_future_output_from_projection: not a future"); return None; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 64de94ea58cf4..9694ce9450c27 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -7,7 +7,7 @@ use rustc_trait_selection::traits::{self, ObligationCause}; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::lang_items::DerefTraitLangItem; +use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem}; use rustc_hir::{is_range_literal, Node}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; @@ -456,8 +456,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if self.can_coerce(ref_ty, expected) { let mut sugg_sp = sp; - if let hir::ExprKind::MethodCall(segment, _sp, args) = &expr.kind { - let clone_trait = self.tcx.lang_items().clone_trait().unwrap(); + if let hir::ExprKind::MethodCall(ref segment, sp, ref args) = expr.kind { + let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp)); if let ([arg], Some(true), sym::clone) = ( &args[..], self.tables.borrow().type_dependent_def_id(expr.hir_id).map(|did| { @@ -635,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ if sp == expr.span && !is_macro => { // Check for `Deref` implementations by constructing a predicate to // prove: `::Output == U` - let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(expr.span)); + let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp)); let item_def_id = self .tcx .associated_items(deref_trait) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 956e09ec52b4a..f06303ecff985 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,7 +100,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::lang_items; +use rustc_hir::lang_items::{ + FutureTraitLangItem, PinTypeLangItem, SizedTraitLangItem, VaListTypeLangItem, +}; use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath}; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; @@ -1342,10 +1344,8 @@ fn check_fn<'a, 'tcx>( // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). let maybe_va_list = if fn_sig.c_variadic { - let va_list_did = tcx.require_lang_item( - lang_items::VaListTypeLangItem, - Some(body.params.last().unwrap().span), - ); + let va_list_did = + tcx.require_lang_item(VaListTypeLangItem, Some(body.params.last().unwrap().span)); let region = tcx.mk_region(ty::ReScope(region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite, @@ -3303,7 +3303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode<'tcx>, ) { if !ty.references_error() { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } } @@ -5142,7 +5142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } let boxed_found = self.tcx.mk_box(found); - let new_found = self.tcx.mk_lang_item(boxed_found, lang_items::PinTypeLangItem).unwrap(); + let new_found = self.tcx.mk_lang_item(boxed_found, PinTypeLangItem).unwrap(); if let (true, Ok(snippet)) = ( self.can_coerce(new_found, expected), self.sess().source_map().span_to_snippet(expr.span), @@ -5298,7 +5298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp = expr.span; // Check for `Future` implementations by constructing a predicate to // prove: `::Output == U` - let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(sp)); let item_def_id = self .tcx .associated_items(future_trait) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c01c4d90c8e17..efa3cd9955b49 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -4,7 +4,9 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::UnsizeTraitLangItem; +use rustc_hir::lang_items::{ + CoerceUnsizedTraitLangItem, DispatchFromDynTraitLangItem, UnsizeTraitLangItem, +}; use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; @@ -145,11 +147,11 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefI fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) { debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); - let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap(); - let impl_hir_id = tcx.hir().as_local_hir_id(impl_did); let span = tcx.hir().span(impl_hir_id); + let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span)); + let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); let target = { @@ -314,22 +316,23 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap(); + + // this provider should only get invoked for local def-ids + let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local()); + let span = tcx.hir().span(impl_hir_id); + + let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span)); let unsize_trait = tcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| { tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); }); - // this provider should only get invoked for local def-ids - let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local()); - let source = tcx.type_of(impl_did); let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); - let span = tcx.hir().span(impl_hir_id); let param_env = tcx.param_env(impl_did); assert!(!source.has_escaping_bound_vars()); From 45ee3360072a4bed1a2625dc03bdae1bd5aee5c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 14 May 2020 22:36:17 -0700 Subject: [PATCH 15/17] Fix {:#?} representation of proc_macro::Literal Before: TokenStream [ Ident { ident: "name", span: #0 bytes(37..41), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(42..43), }, Literal { lit: Lit { kind: Str, symbol: "SNPP", suffix: None }, span: Span { lo: BytePos(44), hi: BytePos(50), ctxt: #0 } }, Punct { ch: ',', spacing: Alone, span: #0 bytes(50..51), }, Ident { ident: "owner", span: #0 bytes(56..61), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(62..63), }, Literal { lit: Lit { kind: Str, symbol: "Canary M Burns", suffix: None }, span: Span { lo: BytePos(64), hi: BytePos(80), ctxt: #0 } }, ] After: TokenStream [ Ident { ident: "name", span: #0 bytes(37..41), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(42..43), }, Literal { kind: Str, symbol: "SNPP", suffix: None, span: #0 bytes(44..50), }, Punct { ch: ',', spacing: Alone, span: #0 bytes(50..51), }, Ident { ident: "owner", span: #0 bytes(56..61), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(62..63), }, Literal { kind: Str, symbol: "Canary M Burns", suffix: None, span: #0 bytes(64..80), }, ] --- src/libproc_macro/bridge/client.rs | 9 +++++++-- src/libproc_macro/bridge/mod.rs | 5 +++-- src/libproc_macro/lib.rs | 1 - src/librustc_expand/proc_macro_server.rs | 11 ++++++++--- .../redundant-semi-proc-macro.stderr | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index d2222d12623f9..a8f6a90ef7631 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -202,10 +202,15 @@ impl Clone for Literal { } } -// FIXME(eddyb) `Literal` should not expose internal `Debug` impls. impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.debug()) + f.debug_struct("Literal") + .field("kind", &format_args!("{}", &self.debug_kind())) + .field("symbol", &self.symbol()) + // format `Some("...")` on one line even in {:#?} mode + .field("suffix", &format_args!("{:?}", &self.suffix())) + .field("span", &self.span()) + .finish() } } diff --git a/src/libproc_macro/bridge/mod.rs b/src/libproc_macro/bridge/mod.rs index a0e7d90f4974e..bf0d8fcee5b8f 100644 --- a/src/libproc_macro/bridge/mod.rs +++ b/src/libproc_macro/bridge/mod.rs @@ -103,8 +103,9 @@ macro_rules! with_api { Literal { fn drop($self: $S::Literal); fn clone($self: &$S::Literal) -> $S::Literal; - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. - fn debug($self: &$S::Literal) -> String; + fn debug_kind($self: &$S::Literal) -> String; + fn symbol($self: &$S::Literal) -> String; + fn suffix($self: &$S::Literal) -> Option; fn integer(n: &str) -> $S::Literal; fn typed_integer(n: &str, kind: &str) -> $S::Literal; fn float(n: &str) -> $S::Literal; diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 31bc61263abe6..f34a39996fe38 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -1134,7 +1134,6 @@ impl fmt::Display for Literal { #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. self.0.fmt(f) } } diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index afc6dc36eb430..b9693c2c86278 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -507,9 +507,14 @@ impl server::Ident for Rustc<'_> { } impl server::Literal for Rustc<'_> { - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. - fn debug(&mut self, literal: &Self::Literal) -> String { - format!("{:?}", literal) + fn debug_kind(&mut self, literal: &Self::Literal) -> String { + format!("{:?}", literal.lit.kind) + } + fn symbol(&mut self, literal: &Self::Literal) -> String { + literal.lit.symbol.to_string() + } + fn suffix(&mut self, literal: &Self::Literal) -> Option { + literal.lit.suffix.as_ref().map(Symbol::to_string) } fn integer(&mut self, n: &str) -> Self::Literal { self.lit(token::Integer, Symbol::intern(n), None) diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index a79fba9bf3f00..bc0c533032413 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(238), hi: BytePos(241), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(483), hi: BytePos(486), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | From 4c4b4c4ab407f0ccdfc71caf443735e5ba62539c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:01:26 -0700 Subject: [PATCH 16/17] Add test of proc_macro::TokenStream's Debug --- .../debug/auxiliary/macro-dump-debug.rs | 15 ++ src/test/ui/proc-macro/debug/dump-debug.rs | 40 +++++ .../ui/proc-macro/debug/dump-debug.stderr | 166 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs create mode 100644 src/test/ui/proc-macro/debug/dump-debug.rs create mode 100644 src/test/ui/proc-macro/debug/dump-debug.stderr diff --git a/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs new file mode 100644 index 0000000000000..56ad0612f74bd --- /dev/null +++ b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "macro_dump_debug"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dump_debug(tokens: TokenStream) -> TokenStream { + eprintln!("{:?}", tokens); + eprintln!("{:#?}", tokens); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/debug/dump-debug.rs b/src/test/ui/proc-macro/debug/dump-debug.rs new file mode 100644 index 0000000000000..0ed36b690f49b --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.rs @@ -0,0 +1,40 @@ +// run-pass +// aux-build:macro-dump-debug.rs + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/dump-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug.stderr new file mode 100644 index 0000000000000..0aedefd4e6091 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }] +TokenStream [ + Ident { + ident: "ident", + span: #0 bytes(130..135), + }, + Ident { + ident: "r#ident", + span: #0 bytes(151..158), + }, + Punct { + ch: ',', + spacing: Alone, + span: #0 bytes(176..177), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '>', + spacing: Alone, + span: #0 bytes(205..206), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: #0 bytes(230..232), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: #0 bytes(258..259), + }, + ], + span: #0 bytes(257..260), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(315..316), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: #0 bytes(321..324), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: #0 bytes(329..332), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: #0 bytes(337..341), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: #0 bytes(346..350), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: #0 bytes(355..363), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: #0 bytes(368..374), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: #0 bytes(379..389), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: #0 bytes(394..397), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: #0 bytes(402..406), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: #0 bytes(437..439), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: #0 bytes(444..448), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: #0 bytes(453..457), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(462..467), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(472..477), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(482..491), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(496..503), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(508..519), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: #0 bytes(524..528), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(533..538), + }, +] From bea2c59ea56cb3daa7e3bacabd7c95f002f9aca0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:35:46 -0700 Subject: [PATCH 17/17] Clarify use of format_args in Debug for Literal --- src/libproc_macro/bridge/client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index a8f6a90ef7631..283aa25b0ea13 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -205,6 +205,7 @@ impl Clone for Literal { impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Literal") + // format the kind without quotes, as in `kind: Float` .field("kind", &format_args!("{}", &self.debug_kind())) .field("symbol", &self.symbol()) // format `Some("...")` on one line even in {:#?} mode