From e09e6df787df074becd7b1b5b1138f517dd788d5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 28 Oct 2022 21:54:09 -0700 Subject: [PATCH 001/137] rustdoc: compute maximum Levenshtein distance based on the query The heuristic is pretty close to the name resolver. Fixes #103357 --- src/librustdoc/html/static/js/search.js | 149 +++++++++++++----------- tests/rustdoc-js-std/typed-query.js | 3 - tests/rustdoc-js/doc-alias.js | 2 - 3 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 88592fa0c84c..251e806c2d90 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -112,7 +112,6 @@ function levenshtein(s1, s2) { } function initSearch(rawSearchIndex) { - const MAX_LEV_DISTANCE = 3; const MAX_RESULTS = 200; const NO_TYPE_FILTER = -1; /** @@ -897,13 +896,13 @@ function initSearch(rawSearchIndex) { * @param {QueryElement} elem - The element from the parsed query. * @param {integer} defaultLev - This is the value to return in case there are no generics. * - * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`. + * @return {integer} - Returns the best match (if any) or `maxLevDistance + 1`. */ - function checkGenerics(row, elem, defaultLev) { + function checkGenerics(row, elem, defaultLev, maxLevDistance) { if (row.generics.length === 0) { - return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1; + return elem.generics.length === 0 ? defaultLev : maxLevDistance + 1; } else if (row.generics.length > 0 && row.generics[0].name === null) { - return checkGenerics(row.generics[0], elem, defaultLev); + return checkGenerics(row.generics[0], elem, defaultLev, maxLevDistance); } // The names match, but we need to be sure that all generics kinda // match as well. @@ -914,8 +913,8 @@ function initSearch(rawSearchIndex) { elem_name = entry.name; if (elem_name === "") { // Pure generic, needs to check into it. - if (checkGenerics(entry, elem, MAX_LEV_DISTANCE + 1) !== 0) { - return MAX_LEV_DISTANCE + 1; + if (checkGenerics(entry, elem, maxLevDistance + 1, maxLevDistance) !== 0) { + return maxLevDistance + 1; } continue; } @@ -942,7 +941,7 @@ function initSearch(rawSearchIndex) { } } if (match === null) { - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } elems[match] -= 1; if (elems[match] === 0) { @@ -951,7 +950,7 @@ function initSearch(rawSearchIndex) { } return 0; } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } /** @@ -963,10 +962,10 @@ function initSearch(rawSearchIndex) { * * @return {integer} - Returns a Levenshtein distance to the best match. */ - function checkIfInGenerics(row, elem) { - let lev = MAX_LEV_DISTANCE + 1; + function checkIfInGenerics(row, elem, maxLevDistance) { + let lev = maxLevDistance + 1; for (const entry of row.generics) { - lev = Math.min(checkType(entry, elem, true), lev); + lev = Math.min(checkType(entry, elem, true, maxLevDistance), lev); if (lev === 0) { break; } @@ -983,15 +982,15 @@ function initSearch(rawSearchIndex) { * @param {boolean} literalSearch * * @return {integer} - Returns a Levenshtein distance to the best match. If there is - * no match, returns `MAX_LEV_DISTANCE + 1`. + * no match, returns `maxLevDistance + 1`. */ - function checkType(row, elem, literalSearch) { + function checkType(row, elem, literalSearch, maxLevDistance) { if (row.name === null) { // This is a pure "generic" search, no need to run other checks. if (row.generics.length > 0) { - return checkIfInGenerics(row, elem); + return checkIfInGenerics(row, elem, maxLevDistance); } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } let lev = levenshtein(row.name, elem.name); @@ -1005,9 +1004,9 @@ function initSearch(rawSearchIndex) { return 0; } } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } else if (elem.generics.length > 0) { - return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1); + return checkGenerics(row, elem, maxLevDistance + 1, maxLevDistance); } return 0; } else if (row.generics.length > 0) { @@ -1017,22 +1016,20 @@ function initSearch(rawSearchIndex) { } // The name didn't match so we now check if the type we're looking for is inside // the generics! - lev = checkIfInGenerics(row, elem); - // Now whatever happens, the returned distance is "less good" so we should mark - // it as such, and so we add 0.5 to the distance to make it "less good". - return lev + 0.5; - } else if (lev > MAX_LEV_DISTANCE) { + lev = Math.min(lev, checkIfInGenerics(row, elem, maxLevDistance)); + return lev; + } else if (lev > maxLevDistance) { // So our item's name doesn't match at all and has generics. // // Maybe it's present in a sub generic? For example "f>>()", if we're // looking for "B", we'll need to go down. - return checkIfInGenerics(row, elem); + return checkIfInGenerics(row, elem, maxLevDistance); } else { // At this point, the name kinda match and we have generics to check, so // let's go! - const tmp_lev = checkGenerics(row, elem, lev); - if (tmp_lev > MAX_LEV_DISTANCE) { - return MAX_LEV_DISTANCE + 1; + const tmp_lev = checkGenerics(row, elem, lev, maxLevDistance); + if (tmp_lev > maxLevDistance) { + return maxLevDistance + 1; } // We compute the median value of both checks and return it. return (tmp_lev + lev) / 2; @@ -1040,7 +1037,7 @@ function initSearch(rawSearchIndex) { } else if (elem.generics.length > 0) { // In this case, we were expecting generics but there isn't so we simply reject this // one. - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } // No generics on our query or on the target type so we can return without doing // anything else. @@ -1055,23 +1052,26 @@ function initSearch(rawSearchIndex) { * @param {integer} typeFilter * * @return {integer} - Returns a Levenshtein distance to the best match. If there is no - * match, returns `MAX_LEV_DISTANCE + 1`. + * match, returns `maxLevDistance + 1`. */ - function findArg(row, elem, typeFilter) { - let lev = MAX_LEV_DISTANCE + 1; + function findArg(row, elem, typeFilter, maxLevDistance) { + let lev = maxLevDistance + 1; if (row && row.type && row.type.inputs && row.type.inputs.length > 0) { for (const input of row.type.inputs) { if (!typePassesFilter(typeFilter, input.ty)) { continue; } - lev = Math.min(lev, checkType(input, elem, parsedQuery.literalSearch)); + lev = Math.min( + lev, + checkType(input, elem, parsedQuery.literalSearch, maxLevDistance) + ); if (lev === 0) { return 0; } } } - return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev; + return parsedQuery.literalSearch ? maxLevDistance + 1 : lev; } /** @@ -1082,10 +1082,10 @@ function initSearch(rawSearchIndex) { * @param {integer} typeFilter * * @return {integer} - Returns a Levenshtein distance to the best match. If there is no - * match, returns `MAX_LEV_DISTANCE + 1`. + * match, returns `maxLevDistance + 1`. */ - function checkReturned(row, elem, typeFilter) { - let lev = MAX_LEV_DISTANCE + 1; + function checkReturned(row, elem, typeFilter, maxLevDistance) { + let lev = maxLevDistance + 1; if (row && row.type && row.type.output.length > 0) { const ret = row.type.output; @@ -1093,20 +1093,23 @@ function initSearch(rawSearchIndex) { if (!typePassesFilter(typeFilter, ret_ty.ty)) { continue; } - lev = Math.min(lev, checkType(ret_ty, elem, parsedQuery.literalSearch)); + lev = Math.min( + lev, + checkType(ret_ty, elem, parsedQuery.literalSearch, maxLevDistance) + ); if (lev === 0) { return 0; } } } - return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev; + return parsedQuery.literalSearch ? maxLevDistance + 1 : lev; } - function checkPath(contains, ty) { + function checkPath(contains, ty, maxLevDistance) { if (contains.length === 0) { return 0; } - let ret_lev = MAX_LEV_DISTANCE + 1; + let ret_lev = maxLevDistance + 1; const path = ty.path.split("::"); if (ty.parent && ty.parent.name) { @@ -1116,7 +1119,7 @@ function initSearch(rawSearchIndex) { const length = path.length; const clength = contains.length; if (clength > length) { - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } for (let i = 0; i < length; ++i) { if (i + clength > length) { @@ -1126,7 +1129,7 @@ function initSearch(rawSearchIndex) { let aborted = false; for (let x = 0; x < clength; ++x) { const lev = levenshtein(path[i + x], contains[x]); - if (lev > MAX_LEV_DISTANCE) { + if (lev > maxLevDistance) { aborted = true; break; } @@ -1231,7 +1234,7 @@ function initSearch(rawSearchIndex) { * following condition: * * * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0. - * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`. + * * If it is not a "literal search", `lev` must be <= `maxLevDistance`. * * The `results` map contains information which will be used to sort the search results: * @@ -1249,8 +1252,8 @@ function initSearch(rawSearchIndex) { * @param {integer} lev * @param {integer} path_lev */ - function addIntoResults(results, fullId, id, index, lev, path_lev) { - const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1; + function addIntoResults(results, fullId, id, index, lev, path_lev, maxLevDistance) { + const inBounds = lev <= maxLevDistance || index !== -1; if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) { if (results[fullId] !== undefined) { const result = results[fullId]; @@ -1289,7 +1292,8 @@ function initSearch(rawSearchIndex) { elem, results_others, results_in_args, - results_returned + results_returned, + maxLevDistance ) { if (!row || (filterCrates !== null && row.crate !== filterCrates)) { return; @@ -1298,13 +1302,13 @@ function initSearch(rawSearchIndex) { const fullId = row.id; const searchWord = searchWords[pos]; - const in_args = findArg(row, elem, parsedQuery.typeFilter); - const returned = checkReturned(row, elem, parsedQuery.typeFilter); + const in_args = findArg(row, elem, parsedQuery.typeFilter, maxLevDistance); + const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxLevDistance); // path_lev is 0 because no parent path information is currently stored // in the search index - addIntoResults(results_in_args, fullId, pos, -1, in_args, 0); - addIntoResults(results_returned, fullId, pos, -1, returned, 0); + addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxLevDistance); + addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxLevDistance); if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) { return; @@ -1328,16 +1332,16 @@ function initSearch(rawSearchIndex) { // No need to check anything else if it's a "pure" generics search. if (elem.name.length === 0) { if (row.type !== null) { - lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1); + lev = checkGenerics(row.type, elem, maxLevDistance + 1, maxLevDistance); // path_lev is 0 because we know it's empty - addIntoResults(results_others, fullId, pos, index, lev, 0); + addIntoResults(results_others, fullId, pos, index, lev, 0, maxLevDistance); } return; } if (elem.fullPath.length > 1) { - path_lev = checkPath(elem.pathWithoutLast, row); - if (path_lev > MAX_LEV_DISTANCE) { + path_lev = checkPath(elem.pathWithoutLast, row, maxLevDistance); + if (path_lev > maxLevDistance) { return; } } @@ -1351,11 +1355,11 @@ function initSearch(rawSearchIndex) { lev = levenshtein(searchWord, elem.pathLast); - if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) { + if (index === -1 && lev + path_lev > maxLevDistance) { return; } - addIntoResults(results_others, fullId, pos, index, lev, path_lev); + addIntoResults(results_others, fullId, pos, index, lev, path_lev, maxLevDistance); } /** @@ -1367,7 +1371,7 @@ function initSearch(rawSearchIndex) { * @param {integer} pos - Position in the `searchIndex`. * @param {Object} results */ - function handleArgs(row, pos, results) { + function handleArgs(row, pos, results, maxLevDistance) { if (!row || (filterCrates !== null && row.crate !== filterCrates)) { return; } @@ -1379,7 +1383,7 @@ function initSearch(rawSearchIndex) { function checkArgs(elems, callback) { for (const elem of elems) { // There is more than one parameter to the query so all checks should be "exact" - const lev = callback(row, elem, NO_TYPE_FILTER); + const lev = callback(row, elem, NO_TYPE_FILTER, maxLevDistance); if (lev <= 1) { nbLev += 1; totalLev += lev; @@ -1400,12 +1404,21 @@ function initSearch(rawSearchIndex) { return; } const lev = Math.round(totalLev / nbLev); - addIntoResults(results, row.id, pos, 0, lev, 0); + addIntoResults(results, row.id, pos, 0, lev, 0, maxLevDistance); } function innerRunQuery() { let elem, i, nSearchWords, in_returned, row; + let queryLen = 0; + for (const elem of parsedQuery.elems) { + queryLen += elem.name.length; + } + for (const elem of parsedQuery.returned) { + queryLen += elem.name.length; + } + const maxLevDistance = Math.floor(queryLen / 3); + if (parsedQuery.foundElems === 1) { if (parsedQuery.elems.length === 1) { elem = parsedQuery.elems[0]; @@ -1418,7 +1431,8 @@ function initSearch(rawSearchIndex) { elem, results_others, results_in_args, - results_returned + results_returned, + maxLevDistance ); } } else if (parsedQuery.returned.length === 1) { @@ -1426,13 +1440,18 @@ function initSearch(rawSearchIndex) { elem = parsedQuery.returned[0]; for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { row = searchIndex[i]; - in_returned = checkReturned(row, elem, parsedQuery.typeFilter); - addIntoResults(results_others, row.id, i, -1, in_returned); + in_returned = checkReturned( + row, + elem, + parsedQuery.typeFilter, + maxLevDistance + ); + addIntoResults(results_others, row.id, i, -1, in_returned, maxLevDistance); } } } else if (parsedQuery.foundElems > 0) { for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { - handleArgs(searchIndex[i], i, results_others); + handleArgs(searchIndex[i], i, results_others, maxLevDistance); } } } @@ -1470,7 +1489,7 @@ function initSearch(rawSearchIndex) { * * @return {boolean} - Whether the result is valid or not */ - function validateResult(name, path, keys, parent) { + function validateResult(name, path, keys, parent, maxLevDistance) { if (!keys || !keys.length) { return true; } @@ -1485,7 +1504,7 @@ function initSearch(rawSearchIndex) { (parent !== undefined && parent.name !== undefined && parent.name.toLowerCase().indexOf(key) > -1) || // lastly check to see if the name was a levenshtein match - levenshtein(name, key) <= MAX_LEV_DISTANCE)) { + levenshtein(name, key) <= maxLevDistance)) { return false; } } diff --git a/tests/rustdoc-js-std/typed-query.js b/tests/rustdoc-js-std/typed-query.js index fd5c5489d79c..9d7e73a7999c 100644 --- a/tests/rustdoc-js-std/typed-query.js +++ b/tests/rustdoc-js-std/typed-query.js @@ -10,8 +10,5 @@ const EXPECTED = { { 'path': 'std', 'name': 'eprint' }, { 'path': 'std', 'name': 'eprintln' }, { 'path': 'std::pin', 'name': 'pin' }, - { 'path': 'std::future', 'name': 'join' }, - { 'path': 'std', 'name': 'line' }, - { 'path': 'std', 'name': 'write' }, ], }; diff --git a/tests/rustdoc-js/doc-alias.js b/tests/rustdoc-js/doc-alias.js index 7bb0cbe388fe..62c8e7a74b94 100644 --- a/tests/rustdoc-js/doc-alias.js +++ b/tests/rustdoc-js/doc-alias.js @@ -1,5 +1,3 @@ -// exact-check - const QUERY = [ 'StructItem', 'StructFieldItem', From 8211760b9188d3d008e1e1c0cc27292dde3eb162 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 28 Oct 2022 23:07:36 -0700 Subject: [PATCH 002/137] rustdoc: update test case to deal with "coo" only accepting dist=1 --- tests/rustdoc-gui/src/test_docs/lib.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index 51250439694b..6ad1e8b4f673 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -340,7 +340,7 @@ pub mod details { pub mod doc_block_table { pub trait DocBlockTableTrait { - fn func(); + fn foo(); } /// Struct doc. @@ -359,7 +359,7 @@ pub mod doc_block_table { /// | header1 | header2 | /// |--------------------------|--------------------------| /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum | - fn func() { + fn foo() { println!(); } } @@ -474,3 +474,15 @@ impl TypeWithImplDoc { /// /// pub mod codeblock_sub {} +pub mod search_results { + + pub struct SearchResults { + pub foo: i32, + } + + #[macro_export] + macro_rules! foo { + () => {}; + } + +} From 39fd4bb476fe600dccb424c94fce1e270bd7694f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 21 Jan 2023 00:11:08 -0700 Subject: [PATCH 003/137] rustdoc: update test cases to match with stricter match criteria --- tests/rustdoc-js-std/typed-query.js | 1 - tests/rustdoc-js/module-substring.js | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/rustdoc-js-std/typed-query.js b/tests/rustdoc-js-std/typed-query.js index 9d7e73a7999c..eeb3e1888695 100644 --- a/tests/rustdoc-js-std/typed-query.js +++ b/tests/rustdoc-js-std/typed-query.js @@ -9,6 +9,5 @@ const EXPECTED = { { 'path': 'std', 'name': 'println' }, { 'path': 'std', 'name': 'eprint' }, { 'path': 'std', 'name': 'eprintln' }, - { 'path': 'std::pin', 'name': 'pin' }, ], }; diff --git a/tests/rustdoc-js/module-substring.js b/tests/rustdoc-js/module-substring.js index a446c39ebad5..f17a97f13dc7 100644 --- a/tests/rustdoc-js/module-substring.js +++ b/tests/rustdoc-js/module-substring.js @@ -4,6 +4,5 @@ const EXPECTED = { 'others': [ { 'path': 'module_substring::Sig', 'name': 'pc' }, { 'path': 'module_substring::Si', 'name': 'pc' }, - { 'path': 'module_substring::Si', 'name': 'pa' }, ], }; From 2a67e99d7d234f8f225d963114c85403fff8272c Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Tue, 3 Jan 2023 19:54:11 -0800 Subject: [PATCH 004/137] Point at specific field in struct literal when trait fulfillment fails --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 457 ++++++++++++++++++ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 84 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 1 + compiler/rustc_hir_typeck/src/method/probe.rs | 1 + compiler/rustc_infer/src/traits/util.rs | 48 +- compiler/rustc_middle/src/traits/mod.rs | 2 + .../src/traits/select/confirmation.rs | 1 + .../src/traits/select/mod.rs | 3 +- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/tools/cargo | 2 +- tests/ui/derives/deriving-copyclone.stderr | 24 +- .../blame-trait-error.rs | 28 ++ .../blame-trait-error.stderr | 35 ++ .../blame-trait-error-spans-on-exprs.rs | 131 +++++ .../blame-trait-error-spans-on-exprs.stderr | 380 +++++++++++++++ .../issue-62203-hrtb-ice.rs | 16 +- .../issue-62203-hrtb-ice.stderr | 36 +- .../negated-auto-traits-error.stderr | 4 +- 21 files changed, 1150 insertions(+), 111 deletions(-) create mode 100644 compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs create mode 100644 tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs create mode 100644 tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr create mode 100644 tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs create mode 100644 tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs new file mode 100644 index 000000000000..2eab68050d43 --- /dev/null +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -0,0 +1,457 @@ +use crate::FnCtxt; +use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_middle::ty::{self, DefIdTree, Ty}; +use rustc_trait_selection::traits; + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + /** + * Recursively searches for the most-specific blamable expression. + * For example, if you have a chain of constraints like: + * - want `Vec: Copy` + * - because `Option>: Copy` needs `Vec: Copy` because `impl Copy for Option` + * - because `(Option, bool)` needs `Option>: Copy` because `impl Copy for (A, B)` + * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible` + * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint. + * + * This function only updates the error span. + */ + pub fn blame_specific_expr_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) { + // Whether it succeeded or failed, it likely made some amount of progress. + // In the very worst case, it's just the same `expr` we originally passed in. + let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code( + &error.obligation.cause.code(), + expr, + ) { + Ok(expr) => expr, + Err(expr) => expr, + }; + + // Either way, use this expression to update the error span. + // If it doesn't overlap the existing span at all, use the original span. + // FIXME: It would possibly be better to do this more continuously, at each level... + error.obligation.cause.span = expr + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(error.obligation.cause.span); + } + + fn blame_specific_expr_if_possible_for_obligation_cause_code( + &self, + obligation_cause_code: &traits::ObligationCauseCode<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> { + match obligation_cause_code { + traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => { + // This is the "root"; we assume that the `expr` is already pointing here. + // Therefore, we return `Ok` so that this `expr` can be refined further. + Ok(expr) + } + traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self + .blame_specific_expr_if_possible_for_derived_predicate_obligation( + impl_derived, + expr, + ), + _ => { + // We don't recognize this kind of constraint, so we cannot refine the expression + // any further. + Err(expr) + } + } + } + + /// We want to achieve the error span in the following example: + /// + /// ```ignore (just for demonstration) + /// struct Burrito { + /// filling: Filling, + /// } + /// impl Delicious for Burrito {} + /// fn eat_delicious_food(_food: Food) {} + /// + /// fn will_type_error() { + /// eat_delicious_food(Burrito { filling: Kale }); + /// } // ^--- The trait bound `Kale: Delicious` + /// // is not satisfied + /// ``` + /// + /// Without calling this function, the error span will cover the entire argument expression. + /// + /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent + /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize. + /// + /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be + /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be + /// only a partial success - but it cannot be refined even further. + fn blame_specific_expr_if_possible_for_derived_predicate_obligation( + &self, + obligation: &traits::ImplDerivedObligationCause<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> { + // First, we attempt to refine the `expr` for our span using the parent obligation. + // If this cannot be done, then we are already stuck, so we stop early (hence the use + // of the `?` try operator here). + let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code( + &*obligation.derived.parent_code, + expr, + )?; + + // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about. + // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of + // that struct type. + let impl_trait_self_ref: Option> = + self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder()); + + let Some(impl_trait_self_ref) = impl_trait_self_ref else { + // It is possible that this is absent. In this case, we make no progress. + return Err(expr); + }; + + // We only really care about the `Self` type itself, which we extract from the ref. + let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty(); + + let impl_predicates: ty::GenericPredicates<'tcx> = + self.tcx.predicates_of(obligation.impl_def_id); + let Some(impl_predicate_index) = obligation.impl_def_predicate_index else { + // We don't have the index, so we can only guess. + return Err(expr); + }; + + if impl_predicate_index >= impl_predicates.predicates.len() { + // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things. + return Err(expr); + } + let relevant_broken_predicate: ty::PredicateKind<'tcx> = + impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder(); + + match relevant_broken_predicate { + ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => { + // ... + self.blame_specific_part_of_expr_corresponding_to_generic_param( + broken_trait.trait_ref.self_ty().into(), + expr, + impl_self_ty.into(), + ) + } + _ => Err(expr), + } + } + + /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`. + /// For example, given + /// - expr: `(Some(vec![1, 2, 3]), false)` + /// - param: `T` + /// - in_ty: `(Option, bool)` + /// we would drill until we arrive at `vec![1, 2, 3]`. + /// + /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`), + /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to + /// `foo()` and then return `Err("foo()")`. + /// + /// This means that you can (and should) use the `?` try operator to chain multiple calls to this + /// function with different types, since you can only continue drilling the second time if you + /// succeeded the first time. + fn blame_specific_part_of_expr_corresponding_to_generic_param( + &self, + param: ty::GenericArg<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + in_ty: ty::GenericArg<'tcx>, + ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> { + if param == in_ty { + // The types match exactly, so we have drilled as far as we can. + return Ok(expr); + } + + let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else { + return Err(expr); + }; + + if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) = + (&expr.kind, in_ty.kind()) + { + if in_ty_elements.len() != expr_elements.len() { + return Err(expr); + } + // Find out which of `in_ty_elements` refer to `param`. + // FIXME: It may be better to take the first if there are multiple, + // just so that the error points to a smaller expression. + let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| { + Self::find_param_in_ty((*in_ty_elem).into(), param) + })) else { + // The param is not mentioned, or it is mentioned in multiple indexes. + return Err(expr); + }; + + return self.blame_specific_part_of_expr_corresponding_to_generic_param( + param, + drill_expr, + drill_ty.into(), + ); + } + + if let ( + hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest), + ty::Adt(in_ty_adt, in_ty_adt_generic_args), + ) = (&expr.kind, in_ty.kind()) + { + // First, confirm that this struct is the same one as in the types, and if so, + // find the right variant. + let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else { + return Err(expr); + }; + + let variant_def_id = match expr_struct_def_kind { + hir::def::DefKind::Struct => { + if in_ty_adt.did() != expr_struct_def_id { + // FIXME: Deal with type aliases? + return Err(expr); + } + expr_struct_def_id + } + hir::def::DefKind::Variant => { + // If this is a variant, its parent is the type definition. + if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) { + // FIXME: Deal with type aliases? + return Err(expr); + } + expr_struct_def_id + } + _ => { + return Err(expr); + } + }; + + // We need to know which of the generic parameters mentions our target param. + // We expect that at least one of them does, since it is expected to be mentioned. + let Some((drill_generic_index, generic_argument_type)) = + Self::is_iterator_singleton( + in_ty_adt_generic_args.iter().enumerate().filter( + |(_index, in_ty_generic)| { + Self::find_param_in_ty(*in_ty_generic, param) + }, + ), + ) else { + return Err(expr); + }; + + let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did()); + if drill_generic_index >= struct_generic_parameters.params.len() { + return Err(expr); + } + + let param_to_point_at_in_struct = self.tcx.mk_param_from_def( + struct_generic_parameters.param_at(drill_generic_index, self.tcx), + ); + + // We make 3 steps: + // Suppose we have a type like + // ```ignore (just for demonstration) + // struct ExampleStruct { + // enabled: bool, + // item: Option<(usize, T, bool)>, + // } + // + // f(ExampleStruct { + // enabled: false, + // item: Some((0, Box::new(String::new()), 1) }, true)), + // }); + // ``` + // Here, `f` is passed a `ExampleStruct>`, but it wants + // for `String: Copy`, which isn't true here. + // + // (1) First, we drill into `.item` and highlight that expression + // (2) Then we use the template type `Option<(usize, T, bool)>` to + // drill into the `T`, arriving at a `Box` expression. + // (3) Then we keep going, drilling into this expression using our + // outer contextual information. + + // (1) Find the (unique) field which mentions the type in our constraint: + let (field_expr, field_type) = self + .point_at_field_if_possible( + in_ty_adt.did(), + param_to_point_at_in_struct, + variant_def_id, + expr_struct_fields, + ) + .ok_or(expr)?; + + // (2) Continue drilling into the struct, ignoring the struct's + // generic argument types. + let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param( + param_to_point_at_in_struct, + field_expr, + field_type.into(), + )?; + + // (3) Continue drilling into the expression, having "passed + // through" the struct entirely. + return self.blame_specific_part_of_expr_corresponding_to_generic_param( + param, + expr, + generic_argument_type, + ); + } + + if let ( + hir::ExprKind::Call(expr_callee, expr_args), + ty::Adt(in_ty_adt, in_ty_adt_generic_args), + ) = (&expr.kind, in_ty.kind()) + { + let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else { + // FIXME: This case overlaps with another one worth handling, + // which should happen above since it applies to non-ADTs: + // we can drill down into regular generic functions. + return Err(expr); + }; + // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`. + + let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else { + return Err(expr); + }; + + let variant_def_id = match expr_struct_def_kind { + hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { + if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { + // FIXME: Deal with type aliases? + return Err(expr); + } + self.tcx.parent(expr_ctor_def_id) + } + hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { + // If this is a variant, its parent is the type definition. + if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { + // FIXME: Deal with type aliases? + return Err(expr); + } + expr_ctor_def_id + } + _ => { + return Err(expr); + } + }; + + // We need to know which of the generic parameters mentions our target param. + // We expect that at least one of them does, since it is expected to be mentioned. + let Some((drill_generic_index, generic_argument_type)) = + Self::is_iterator_singleton( + in_ty_adt_generic_args.iter().enumerate().filter( + |(_index, in_ty_generic)| { + Self::find_param_in_ty(*in_ty_generic, param) + }, + ), + ) else { + return Err(expr); + }; + + let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did()); + if drill_generic_index >= struct_generic_parameters.params.len() { + return Err(expr); + } + + let param_to_point_at_in_struct = self.tcx.mk_param_from_def( + struct_generic_parameters.param_at(drill_generic_index, self.tcx), + ); + + // We make 3 steps: + // Suppose we have a type like + // ```ignore (just for demonstration) + // struct ExampleStruct { + // enabled: bool, + // item: Option<(usize, T, bool)>, + // } + // + // f(ExampleStruct { + // enabled: false, + // item: Some((0, Box::new(String::new()), 1) }, true)), + // }); + // ``` + // Here, `f` is passed a `ExampleStruct>`, but it wants + // for `String: Copy`, which isn't true here. + // + // (1) First, we drill into `.item` and highlight that expression + // (2) Then we use the template type `Option<(usize, T, bool)>` to + // drill into the `T`, arriving at a `Box` expression. + // (3) Then we keep going, drilling into this expression using our + // outer contextual information. + + // (1) Find the (unique) field index which mentions the type in our constraint: + let Some((field_index, field_type)) = Self::is_iterator_singleton( + in_ty_adt + .variant_with_id(variant_def_id) + .fields + .iter() + .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args)) + .enumerate() + .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param)) + ) else { + return Err(expr); + }; + + if field_index >= expr_args.len() { + return Err(expr); + } + + // (2) Continue drilling into the struct, ignoring the struct's + // generic argument types. + let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param( + param_to_point_at_in_struct, + &expr_args[field_index], + field_type.into(), + )?; + + // (3) Continue drilling into the expression, having "passed + // through" the struct entirely. + return self.blame_specific_part_of_expr_corresponding_to_generic_param( + param, + expr, + generic_argument_type, + ); + } + + // At this point, none of the basic patterns matched. + // One major possibility which remains is that we have a function call. + // In this case, it's often possible to dive deeper into the call to find something to blame, + // but this is not always possible. + + Err(expr) + } + + // FIXME: This can be made into a private, non-impl function later. + /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references + /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param. + pub fn find_param_in_ty( + ty: ty::GenericArg<'tcx>, + param_to_point_at: ty::GenericArg<'tcx>, + ) -> bool { + let mut walk = ty.walk(); + while let Some(arg) = walk.next() { + if arg == param_to_point_at { + return true; + } else if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Alias(ty::Projection, ..) = ty.kind() + { + // This logic may seem a bit strange, but typically when + // we have a projection type in a function signature, the + // argument that's being passed into that signature is + // not actually constraining that projection's substs in + // a meaningful way. So we skip it, and see improvements + // in some UI tests. + walk.skip_current_subtree(); + } + } + false + } + + // FIXME: This can be made into a private, non-impl function later. + /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise. + pub fn is_iterator_singleton(mut iterator: impl Iterator) -> Option { + match (iterator.next(), iterator.next()) { + (_, Some(_)) => None, + (first, _) => first, + } + } +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c9609e694398..56b256cfbe4f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -34,9 +34,10 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext} use std::iter; use std::mem; -use std::ops::ControlFlow; use std::slice; +use std::ops::ControlFlow; + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn check_casts(&mut self) { // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors @@ -1837,7 +1838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .flatten() { - if self.point_at_arg_if_possible( + if self.blame_specific_arg_if_possible( error, def_id, param, @@ -1867,7 +1868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .flatten() { - if self.point_at_arg_if_possible( + if self.blame_specific_arg_if_possible( error, def_id, param, @@ -1892,16 +1893,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] { - if let Some(param) = param - && self.point_at_field_if_possible( - error, + if let Some(param) = param { + let refined_expr = self.point_at_field_if_possible( def_id, param, variant_def_id, fields, - ) - { - return true; + ); + + match refined_expr { + None => {} + Some((refined_expr, _)) => { + error.obligation.cause.span = refined_expr + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(refined_expr.span); + return true; + } + } } } } @@ -1934,7 +1943,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn point_at_arg_if_possible( + /// - `blame_specific_*` means that the function will recursively traverse the expression, + /// looking for the most-specific-possible span to blame. + /// + /// - `point_at_*` means that the function will only go "one level", pointing at the specific + /// expression mentioned. + /// + /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside + /// the provided function call expression, and mark it as responsible for the fullfillment + /// error. + fn blame_specific_arg_if_possible( &self, error: &mut traits::FulfillmentError<'tcx>, def_id: DefId, @@ -1953,13 +1971,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .inputs() .iter() .enumerate() - .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at)) + .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at)) .collect(); // If there's one field that references the given generic, great! if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = receiver .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) { + error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span); + + if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) { + // This is more specific than pointing at the entire argument. + self.blame_specific_expr_if_possible(error, arg_expr) + } + error.obligation.cause.map_code(|parent_code| { ObligationCauseCode::FunctionArgumentObligation { arg_hir_id: arg.hir_id, @@ -1977,14 +2002,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn point_at_field_if_possible( + // FIXME: Make this private and move to mod adjust_fulfillment_errors + pub fn point_at_field_if_possible( &self, - error: &mut traits::FulfillmentError<'tcx>, def_id: DefId, param_to_point_at: ty::GenericArg<'tcx>, variant_def_id: DefId, expr_fields: &[hir::ExprField<'tcx>], - ) -> bool { + ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> { let def = self.tcx.adt_def(def_id); let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id); @@ -1994,7 +2019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .filter(|field| { let field_ty = field.ty(self.tcx, identity_substs); - find_param_in_ty(field_ty, param_to_point_at) + Self::find_param_in_ty(field_ty.into(), param_to_point_at) }) .collect(); @@ -2004,17 +2029,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // same rules that check_expr_struct uses for macro hygiene. if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx) { - error.obligation.cause.span = expr_field - .expr - .span - .find_ancestor_in_same_ctxt(error.obligation.cause.span) - .unwrap_or(expr_field.span); - return true; + return Some((expr_field.expr, self.tcx.type_of(field.did))); } } } - false + None } fn point_at_path_if_possible( @@ -2234,23 +2254,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - -fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>) -> bool { - let mut walk = ty.walk(); - while let Some(arg) = walk.next() { - if arg == param_to_point_at { - return true; - } else if let ty::GenericArgKind::Type(ty) = arg.unpack() - && let ty::Alias(ty::Projection, ..) = ty.kind() - { - // This logic may seem a bit strange, but typically when - // we have a projection type in a function signature, the - // argument that's being passed into that signature is - // not actually constraining that projection's substs in - // a meaningful way. So we skip it, and see improvements - // in some UI tests. - walk.skip_current_subtree(); - } - } - false -} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 428fde642bc0..b1f9a0209645 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -1,4 +1,5 @@ mod _impl; +mod adjust_fulfillment_errors; mod arg_matrix; mod checks; mod suggestions; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 9c06a22315bc..87f5857986b5 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1568,6 +1568,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { traits::ImplDerivedObligationCause { derived, impl_def_id, + impl_def_predicate_index: None, span, }, )) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index cd5bde2a7913..18a966449aa7 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -145,30 +145,32 @@ impl<'tcx> Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(mut pred, span)| { - // when parent predicate is non-const, elaborate it to non-const predicates. - if data.constness == ty::BoundConstness::NotConst { - pred = pred.without_const(tcx); - } + let obligations = + predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { + // when parent predicate is non-const, elaborate it to non-const predicates. + if data.constness == ty::BoundConstness::NotConst { + pred = pred.without_const(tcx); + } - let cause = obligation.cause.clone().derived_cause( - bound_predicate.rebind(data), - |derived| { - traits::ImplDerivedObligation(Box::new( - traits::ImplDerivedObligationCause { - derived, - impl_def_id: data.def_id(), - span, - }, - )) - }, - ); - predicate_obligation( - pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), - obligation.param_env, - cause, - ) - }); + let cause = obligation.cause.clone().derived_cause( + bound_predicate.rebind(data), + |derived| { + traits::ImplDerivedObligation(Box::new( + traits::ImplDerivedObligationCause { + derived, + impl_def_id: data.def_id(), + impl_def_predicate_index: Some(index), + span, + }, + )) + }, + ); + predicate_obligation( + pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), + obligation.param_env, + cause, + ) + }); debug!(?data, ?obligations, "super_predicates"); // Only keep those bounds that we haven't already seen. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d00b26a5a3d0..b26ef2a29931 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -467,6 +467,8 @@ pub enum WellFormedLoc { pub struct ImplDerivedObligationCause<'tcx> { pub derived: DerivedObligationCause<'tcx>, pub impl_def_id: DefId, + /// The index of the derived predicate in the parent impl's predicates. + pub impl_def_predicate_index: Option, pub span: Span, } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 82a59831be30..4aeaf3ce7144 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1224,6 +1224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplDerivedObligation(Box::new(ImplDerivedObligationCause { derived, impl_def_id, + impl_def_predicate_index: None, span: obligation.cause.span, })) }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f90da95d5166..7bfc098e4cdf 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2562,11 +2562,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { assert_eq!(predicates.parent, None); let predicates = predicates.instantiate_own(tcx, substs); let mut obligations = Vec::with_capacity(predicates.len()); - for (predicate, span) in predicates { + for (index, (predicate, span)) in predicates.into_iter().enumerate() { let cause = cause.clone().derived_cause(parent_trait_pred, |derived| { ImplDerivedObligation(Box::new(ImplDerivedObligationCause { derived, impl_def_id: def_id, + impl_def_predicate_index: Some(index), span, })) }); diff --git a/src/doc/book b/src/doc/book index 2cd1b5593d26..2bd5d42c9956 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 2cd1b5593d26dc6a03c20f8619187ad4b2485552 +Subproject commit 2bd5d42c9956369132228da6409f0e68da56c51a diff --git a/src/doc/nomicon b/src/doc/nomicon index 960d610e7f33..8ca261268068 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 960d610e7f33889a2577f5f17c26f0d5c82b30df +Subproject commit 8ca261268068d80c0969260fff15199bad87b587 diff --git a/src/doc/reference b/src/doc/reference index 2cb0ed9ba563..3ae62681ff23 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 2cb0ed9ba56360949f492f9866afe8c293f9f9da +Subproject commit 3ae62681ff236d5528ef7c8c28ba7c6b2ecc6731 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index a9fb7d13eadf..8888f9428fe9 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit a9fb7d13eadfcc5f457962731f105b97f9a7474a +Subproject commit 8888f9428fe9a48f31de6bd2cef9b9bf80791edc diff --git a/src/tools/cargo b/src/tools/cargo index 985d561f0bb9..8c460b2237a6 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 985d561f0bb9b76ec043a2b12511790ec7a2b954 +Subproject commit 8c460b2237a6359a7e3335890db8da049bdd62fc diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 9c4ca01ff377..c0c2215c04ad 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `B: Copy` is not satisfied - --> $DIR/deriving-copyclone.rs:31:13 + --> $DIR/deriving-copyclone.rs:31:26 | LL | is_copy(B { a: 1, b: C }); - | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B` + | ------- ^ the trait `Copy` is not implemented for `B` | | | required by a bound introduced by this call | @@ -19,14 +19,14 @@ LL | fn is_copy(_: T) {} = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | -LL | is_copy(&B { a: 1, b: C }); - | + +LL | is_copy(B { a: 1, b: &C }); + | + error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/deriving-copyclone.rs:32:14 + --> $DIR/deriving-copyclone.rs:32:27 | LL | is_clone(B { a: 1, b: C }); - | -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | -------- ^ the trait `Clone` is not implemented for `B` | | | required by a bound introduced by this call | @@ -43,14 +43,14 @@ LL | fn is_clone(_: T) {} = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | -LL | is_clone(&B { a: 1, b: C }); - | + +LL | is_clone(B { a: 1, b: &C }); + | + error[E0277]: the trait bound `B: Copy` is not satisfied - --> $DIR/deriving-copyclone.rs:35:13 + --> $DIR/deriving-copyclone.rs:35:26 | LL | is_copy(B { a: 1, b: D }); - | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B` + | ------- ^ the trait `Copy` is not implemented for `B` | | | required by a bound introduced by this call | @@ -67,8 +67,8 @@ LL | fn is_copy(_: T) {} = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | -LL | is_copy(&B { a: 1, b: D }); - | + +LL | is_copy(B { a: 1, b: &D }); + | + error: aborting due to 3 previous errors diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs new file mode 100644 index 000000000000..5134c672f5f4 --- /dev/null +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs @@ -0,0 +1,28 @@ +trait T1 {} +trait T2 {} +trait T3 {} +trait T4 {} + +impl T1 for Wrapper {} + +impl T2 for i32 {} +impl T3 for i32 {} + +impl T2 for Burrito {} + +struct Wrapper { + value: W, +} + +struct Burrito { + filling: F, +} + +fn want(_x: V) {} + +fn example(q: Q) { + want(Wrapper { value: Burrito { filling: q } }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr new file mode 100644 index 000000000000..27b002db1306 --- /dev/null +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:24:46 + | +LL | want(Wrapper { value: Burrito { filling: q } }); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `Burrito` to implement `T2` + --> $DIR/blame-trait-error.rs:11:13 + | +LL | impl T2 for Burrito {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error.rs:6:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:21:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs new file mode 100644 index 000000000000..2b75f4324128 --- /dev/null +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs @@ -0,0 +1,131 @@ +// This test examines the error spans reported when a generic `impl` fails. +// For example, if a function wants an `Option` where `T: Copy` but you pass `Some(vec![1, 2])`, +// then we want to point at the `vec![1, 2]` and not the `Some( ... )` expression. + +trait T1 {} +trait T2 {} +trait T3 {} +trait T4 {} + +impl T2 for i32 {} +impl T3 for i32 {} + +struct Wrapper { + value: W, +} +impl T1 for Wrapper {} + +struct Burrito { + spicy: bool, + filling: F, +} +impl T2 for Burrito {} + +struct BurritoTuple(F); +impl T2 for BurritoTuple {} + +enum BurritoKinds { + SmallBurrito { spicy: bool, small_filling: G }, + LargeBurrito { spicy: bool, large_filling: G }, + MultiBurrito { first_filling: G, second_filling: G }, +} +impl T2 for BurritoKinds {} + +struct Taco(bool, H); +impl T2 for Taco {} + +enum TacoKinds { + OneTaco(bool, H), + TwoTacos(bool, H, H), +} +impl T2 for TacoKinds {} + +struct GenericBurrito { + spiciness: Spiciness, + filling: Filling, +} +impl T2 for GenericBurrito {} +struct NotSpicy; + +impl T2 for (A, B) {} +impl T1 for (A, B) {} + +fn want(_x: V) {} + +// Some more-complex examples: +type AliasBurrito = GenericBurrito; + +// The following example is fairly confusing. The idea is that we want to "misdirect" the location +// of the error. + +struct Two { + a: A, + b: B, +} + +impl T1 for Two, Z> {} + +struct DoubleWrapper { + item: Wrapper, +} + +impl T1 for DoubleWrapper {} + +fn example(q: Q) { + // In each of the following examples, we expect the error span to point at the 'q' variable, + // since the missing constraint is `Q: T3`. + + // Verifies for struct: + want(Wrapper { value: Burrito { spicy: false, filling: q } }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for enum with named fields in variant: + want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for tuple struct: + want(Wrapper { value: Taco(false, q) }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for tuple enum variant: + want(Wrapper { value: TacoKinds::OneTaco(false, q) }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for generic type with multiple parameters: + want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for tuple: + want((3, q)); + //~^ ERROR the trait bound `Q: T2` is not satisfied [E0277] + + // Verifies for nested tuple: + want(Wrapper { value: (3, q) }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + // Verifies for nested tuple: + want(((3, q), 5)); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + want(DoubleWrapper { item: Wrapper { value: q } }); + //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277] + + want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } }); + //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277] + + // Verifies for type alias to struct: + want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } }); + //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + want(Two { a: Two { a: (), b: q }, b: () }); + //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277] + + // We *should* blame the 'q'. + // FIXME: Right now, the wrong field is blamed. + want( + Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () }, + //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277] + ); +} + +fn main() {} diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr new file mode 100644 index 000000000000..5f87c670d8ac --- /dev/null +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -0,0 +1,380 @@ +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:79:60 + | +LL | want(Wrapper { value: Burrito { spicy: false, filling: q } }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `Burrito` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13 + | +LL | impl T2 for Burrito {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:83:84 + | +LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `BurritoKinds` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13 + | +LL | impl T2 for BurritoKinds {} + | -- ^^ ^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:87:39 + | +LL | want(Wrapper { value: Taco(false, q) }); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `Taco` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:35:13 + | +LL | impl T2 for Taco {} + | -- ^^ ^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:91:27 + | +LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) }); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `TacoKinds` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:41:13 + | +LL | impl T2 for TacoKinds {} + | -- ^^ ^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:95:74 + | +LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `GenericBurrito` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16 + | +LL | impl T2 for GenericBurrito {} + | -- ^^ ^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T2` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:99:14 + | +LL | want((3, q)); + | ---- ^ the trait `T2` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `(i32, Q)` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20 + | +LL | impl T1 for (A, B) {} + | -- ^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:103:31 + | +LL | want(Wrapper { value: (3, q) }); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `(i32, Q)` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20 + | +LL | impl T2 for (A, B) {} + | -- ^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper<(i32, Q)>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:107:15 + | +LL | want(((3, q), 5)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `(i32, Q)` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20 + | +LL | impl T2 for (A, B) {} + | -- ^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `((i32, Q), i32)` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20 + | +LL | impl T1 for (A, B) {} + | -- ^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T1` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:110:49 + | +LL | want(DoubleWrapper { item: Wrapper { value: q } }); + | ---- ^ the trait `T1` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `DoubleWrapper` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13 + | +LL | impl T1 for DoubleWrapper {} + | -- ^^ ^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T1` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:113:88 + | +LL | want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } }); + | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q` + | +note: required for `DoubleWrapper` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13 + | +LL | impl T1 for DoubleWrapper {} + | -- ^^ ^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `DoubleWrapper>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:117:27 + | +LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } }); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `GenericBurrito` to implement `T2` + --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16 + | +LL | impl T2 for GenericBurrito {} + | -- ^^ ^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required for `Wrapper>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13 + | +LL | impl T1 for Wrapper {} + | -- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T1` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:120:35 + | +LL | want(Two { a: Two { a: (), b: q }, b: () }); + | ---- ^ the trait `T1` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `Two, ()>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19 + | +LL | impl T1 for Two, Z> {} + | -- ^^ ^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T1` is not satisfied + --> $DIR/blame-trait-error-spans-on-exprs.rs:126:59 + | +LL | want( + | ---- required by a bound introduced by this call +LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () }, + | ^ the trait `T1` is not implemented for `Q` + | +note: required for `Two, ()>` to implement `T1` + --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19 + | +LL | impl T1 for Two, Z> {} + | -- ^^ ^^^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `Two, ()>>, ()>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs index e70f6fc3430f..6d3bb9bbb771 100644 --- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs @@ -35,16 +35,14 @@ trait Ty<'a> { } fn main() { - let v = Unit2.m( - L { - //~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4` - //~| ERROR type mismatch - f: |x| { - drop(x); - Unit4 - }, + let v = Unit2.m(L { + //~^ ERROR type mismatch + //~| ERROR to be a closure that returns `Unit3`, but it returns `Unit4` + f: |x| { + drop(x); + Unit4 }, - ); + }); } impl<'a> Ty<'a> for Unit2 { diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr index 810f7c28c004..9faea3a229bd 100644 --- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -1,16 +1,17 @@ -error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` - --> $DIR/issue-62203-hrtb-ice.rs:39:9 +error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:38:21 | -LL | let v = Unit2.m( - | - required by a bound introduced by this call -LL | / L { +LL | let v = Unit2.m(L { + | ___________________-_^ + | | | + | | required by a bound introduced by this call LL | | LL | | -LL | | f: |x| { +LL | | f: |x| { ... | -LL | | }, LL | | }, - | |_________^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` +LL | | }); + | |_____^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` | note: expected this to be `<_ as Ty<'_>>::V` --> $DIR/issue-62203-hrtb-ice.rs:21:14 @@ -30,21 +31,22 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4` - --> $DIR/issue-62203-hrtb-ice.rs:39:9 +error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:41:12]` to be a closure that returns `Unit3`, but it returns `Unit4` + --> $DIR/issue-62203-hrtb-ice.rs:38:21 | -LL | let v = Unit2.m( - | - required by a bound introduced by this call -LL | / L { +LL | let v = Unit2.m(L { + | ___________________-_^ + | | | + | | required by a bound introduced by this call LL | | LL | | -LL | | f: |x| { +LL | | f: |x| { ... | -LL | | }, LL | | }, - | |_________^ expected struct `Unit3`, found struct `Unit4` +LL | | }); + | |_____^ expected struct `Unit3`, found struct `Unit4` | -note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>` +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:41:12: 41:15]>` to implement `for<'r> T0<'r, (&'r u8,)>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index ce690b749f55..b680ce7f9901 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -101,10 +101,10 @@ LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` error[E0277]: `main::TestType` cannot be sent between threads safely - --> $DIR/negated-auto-traits-error.rs:66:13 + --> $DIR/negated-auto-traits-error.rs:66:20 | LL | is_sync(Outer2(TestType)); - | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely + | ------- ^^^^^^^^ `main::TestType` cannot be sent between threads safely | | | required by a bound introduced by this call | From 3b562db1e88b6238ee07113ac3e42d00359b773b Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Mon, 23 Jan 2023 13:49:06 -0800 Subject: [PATCH 005/137] fix up doc submodules --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 2bd5d42c9956..2cd1b5593d26 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 2bd5d42c9956369132228da6409f0e68da56c51a +Subproject commit 2cd1b5593d26dc6a03c20f8619187ad4b2485552 diff --git a/src/doc/nomicon b/src/doc/nomicon index 8ca261268068..960d610e7f33 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 8ca261268068d80c0969260fff15199bad87b587 +Subproject commit 960d610e7f33889a2577f5f17c26f0d5c82b30df diff --git a/src/doc/reference b/src/doc/reference index 3ae62681ff23..2cb0ed9ba563 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3ae62681ff236d5528ef7c8c28ba7c6b2ecc6731 +Subproject commit 2cb0ed9ba56360949f492f9866afe8c293f9f9da diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 8888f9428fe9..a9fb7d13eadf 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 8888f9428fe9a48f31de6bd2cef9b9bf80791edc +Subproject commit a9fb7d13eadfcc5f457962731f105b97f9a7474a From eb13b7bc44d89465a914e9b17a372aea26f207bc Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Mon, 23 Jan 2023 21:43:49 -0800 Subject: [PATCH 006/137] fix cargo submodule --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 8c460b2237a6..985d561f0bb9 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 8c460b2237a6359a7e3335890db8da049bdd62fc +Subproject commit 985d561f0bb9b76ec043a2b12511790ec7a2b954 From 99638a68175c8f8483f58dc6878fe836929fde77 Mon Sep 17 00:00:00 2001 From: Nathan Fenner Date: Mon, 23 Jan 2023 21:54:40 -0800 Subject: [PATCH 007/137] revert change to test source --- .../issue-62203-hrtb-ice.rs | 16 +++++---- .../issue-62203-hrtb-ice.stderr | 36 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs index 6d3bb9bbb771..e70f6fc3430f 100644 --- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs @@ -35,14 +35,16 @@ trait Ty<'a> { } fn main() { - let v = Unit2.m(L { - //~^ ERROR type mismatch - //~| ERROR to be a closure that returns `Unit3`, but it returns `Unit4` - f: |x| { - drop(x); - Unit4 + let v = Unit2.m( + L { + //~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4` + //~| ERROR type mismatch + f: |x| { + drop(x); + Unit4 + }, }, - }); + ); } impl<'a> Ty<'a> for Unit2 { diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr index 9faea3a229bd..810f7c28c004 100644 --- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -1,17 +1,16 @@ -error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` - --> $DIR/issue-62203-hrtb-ice.rs:38:21 +error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 | -LL | let v = Unit2.m(L { - | ___________________-_^ - | | | - | | required by a bound introduced by this call +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { LL | | LL | | -LL | | f: |x| { +LL | | f: |x| { ... | +LL | | }, LL | | }, -LL | | }); - | |_____^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + | |_________^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` | note: expected this to be `<_ as Ty<'_>>::V` --> $DIR/issue-62203-hrtb-ice.rs:21:14 @@ -31,22 +30,21 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:41:12]` to be a closure that returns `Unit3`, but it returns `Unit4` - --> $DIR/issue-62203-hrtb-ice.rs:38:21 +error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 | -LL | let v = Unit2.m(L { - | ___________________-_^ - | | | - | | required by a bound introduced by this call +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { LL | | LL | | -LL | | f: |x| { +LL | | f: |x| { ... | +LL | | }, LL | | }, -LL | | }); - | |_____^ expected struct `Unit3`, found struct `Unit4` + | |_________^ expected struct `Unit3`, found struct `Unit4` | -note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:41:12: 41:15]>` to implement `for<'r> T0<'r, (&'r u8,)>` +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>` --> $DIR/issue-62203-hrtb-ice.rs:17:16 | LL | impl<'a, A, T> T0<'a, A> for L From 616a0db7d6c4f1c8dd202c06c6cbe919d171edb1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 24 Jan 2023 09:49:33 -0700 Subject: [PATCH 008/137] rustdoc: add test case based on #103357 --- tests/rustdoc-js-std/regex.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/rustdoc-js-std/regex.js diff --git a/tests/rustdoc-js-std/regex.js b/tests/rustdoc-js-std/regex.js new file mode 100644 index 000000000000..a6843c595f7a --- /dev/null +++ b/tests/rustdoc-js-std/regex.js @@ -0,0 +1,10 @@ +// exact-check + +// https://github.com/rust-lang/rust/issues/103357 +const QUERY = 'regex'; + +const EXPECTED = { + 'others': [], + 'in_args': [], + 'returned': [], +}; From 2adf26fc72f354aabd65da176eb9f8806b0d2ef2 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 23 Jan 2023 21:21:35 +0000 Subject: [PATCH 009/137] Add `rust.lto=off` to bootstrap --- config.toml.example | 3 ++- src/bootstrap/compile.rs | 10 ++++++++++ src/bootstrap/config.rs | 4 +++- src/bootstrap/defaults/config.compiler.toml | 2 ++ src/bootstrap/defaults/config.library.toml | 2 ++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/config.toml.example b/config.toml.example index 5e1d2f2e314f..e0f02eac9c34 100644 --- a/config.toml.example +++ b/config.toml.example @@ -646,7 +646,8 @@ changelog-seen = 2 # Select LTO mode that will be used for compiling rustc. By default, thin local LTO # (LTO within a single crate) is used (like for any Rust crate). You can also select -# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib. +# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable +# LTO entirely. #lto = "thin-local" # ============================================================================= diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 68d1db0160a2..07c0d2233cae 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -379,6 +379,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car if stage >= 1 { cargo.rustflag("-Cembed-bitcode=yes"); } + if builder.config.rust_lto == RustcLto::Off { + cargo.rustflag("-Clto=off"); + } // By default, rustc does not include unwind tables unless they are required // for a particular target. They are not required by RISC-V targets, but @@ -722,6 +725,13 @@ impl Step for Rustc { cargo.rustflag("-Cembed-bitcode=yes"); } RustcLto::ThinLocal => { /* Do nothing, this is the default */ } + RustcLto::Off => { + cargo.rustflag("-Clto=off"); + } + } + } else { + if builder.config.rust_lto == RustcLto::Off { + cargo.rustflag("-Clto=off"); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b41d60d51a8b..a28fe612deb7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -332,8 +332,9 @@ impl SplitDebuginfo { } /// LTO mode used for compiling rustc itself. -#[derive(Default, Clone)] +#[derive(Default, Clone, PartialEq)] pub enum RustcLto { + Off, #[default] ThinLocal, Thin, @@ -348,6 +349,7 @@ impl std::str::FromStr for RustcLto { "thin-local" => Ok(RustcLto::ThinLocal), "thin" => Ok(RustcLto::Thin), "fat" => Ok(RustcLto::Fat), + "off" => Ok(RustcLto::Off), _ => Err(format!("Invalid value for rustc LTO: {}", s)), } } diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index 2f4ccb825c4d..b98b13119e8a 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -12,6 +12,8 @@ debug-logging = true incremental = true # Print backtrace on internal compiler errors during bootstrap backtrace-on-ice = true +# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown. +lto = "off" [llvm] # Will download LLVM from CI if available on your platform. diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 7bc054d3a49f..f362c4111f10 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -8,6 +8,8 @@ bench-stage = 0 [rust] # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true +# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown. +lto = "off" [llvm] # Will download LLVM from CI if available on your platform. From af30e3767e196aa63f813f02910f1d085de89146 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:02:31 +0100 Subject: [PATCH 010/137] Fix missing const expression items visit --- src/librustdoc/visit_ast.rs | 519 +++++++++++++++++++----------------- 1 file changed, 280 insertions(+), 239 deletions(-) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index a89d6fa83983..2fbcda35e441 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -5,7 +5,10 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet}; +use rustc_hir::intravisit::{walk_item, Visitor}; use rustc_hir::{Node, CRATE_HIR_ID}; +use rustc_middle::hir::map::Map; +use rustc_middle::hir::nested_filter; use rustc_middle::ty::{DefIdTree, TyCtxt}; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -63,9 +66,6 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: LocalDefId) -> bool false } -// Also, is there some reason that this doesn't use the 'visit' -// framework from syntax?. - pub(crate) struct RustdocVisitor<'a, 'tcx> { cx: &'a mut core::DocContext<'tcx>, view_item_stack: LocalDefIdSet, @@ -73,6 +73,8 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> { /// Are the current module and all of its parents public? inside_public_path: bool, exact_paths: DefIdMap>, + modules: Vec>, + map: Map<'tcx>, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { @@ -80,12 +82,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // If the root is re-exported, terminate all recursion. let mut stack = LocalDefIdSet::default(); stack.insert(CRATE_DEF_ID); + let om = Module::new( + cx.tcx.crate_name(LOCAL_CRATE), + CRATE_DEF_ID, + cx.tcx.hir().root_module().spans.inner_span, + ); + let map = cx.tcx.hir(); + RustdocVisitor { cx, view_item_stack: stack, inlining: false, inside_public_path: true, exact_paths: Default::default(), + modules: vec![om], + map, } } @@ -94,13 +105,226 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did)); } + /// Tries to resolve the target of a `pub use` statement and inlines the + /// target if it is defined locally and would not be documented otherwise, + /// or when it is specifically requested with `please_inline`. + /// (the latter is the case when the import is marked `doc(inline)`) + /// + /// Cross-crate inlining occurs later on during crate cleaning + /// and follows different rules. + /// + /// Returns `true` if the target has been inlined. + fn maybe_inline_local( + &mut self, + def_id: LocalDefId, + res: Res, + renamed: Option, + glob: bool, + please_inline: bool, + ) -> bool { + debug!("maybe_inline_local res: {:?}", res); + + if self.cx.output_format.is_json() { + return false; + } + + let tcx = self.cx.tcx; + let Some(ori_res_did) = res.opt_def_id() else { + return false; + }; + + let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); + // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. + let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline) + || use_attrs.lists(sym::doc).has_word(sym::hidden); + + // For cross-crate impl inlining we need to know whether items are + // reachable in documentation -- a previously unreachable item can be + // made reachable by cross-crate inlining which we're checking here. + // (this is done here because we need to know this upfront). + if !ori_res_did.is_local() && !is_no_inline { + crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did); + return false; + } + + let Some(res_did) = ori_res_did.as_local() else { + return false; + }; + + let is_private = + !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did); + let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did); + + // Only inline if requested or if the item would otherwise be stripped. + if (!please_inline && !is_private && !is_hidden) || is_no_inline { + return false; + } + + if !self.view_item_stack.insert(res_did) { + return false; + } + + let ret = match tcx.hir().get_by_def_id(res_did) { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { + let prev = mem::replace(&mut self.inlining, true); + for &i in m.item_ids { + let i = self.cx.tcx.hir().item(i); + self.visit_item_inner(i, None, Some(def_id)); + } + self.inlining = prev; + true + } + Node::Item(it) if !glob => { + let prev = mem::replace(&mut self.inlining, true); + self.visit_item_inner(it, renamed, Some(def_id)); + self.inlining = prev; + true + } + Node::ForeignItem(it) if !glob => { + let prev = mem::replace(&mut self.inlining, true); + self.visit_foreign_item_inner(it, renamed); + self.inlining = prev; + true + } + _ => false, + }; + self.view_item_stack.remove(&res_did); + ret + } + + fn visit_item_inner( + &mut self, + item: &'tcx hir::Item<'_>, + renamed: Option, + parent_id: Option, + ) -> bool { + debug!("visiting item {:?}", item); + let name = renamed.unwrap_or(item.ident.name); + let tcx = self.cx.tcx; + + let def_id = item.owner_id.to_def_id(); + let is_pub = tcx.visibility(def_id).is_public(); + + if is_pub { + self.store_path(item.owner_id.to_def_id()); + } + + match item.kind { + hir::ItemKind::ForeignMod { items, .. } => { + for item in items { + let item = tcx.hir().foreign_item(item.id); + self.visit_foreign_item_inner(item, None); + } + } + // If we're inlining, skip private items or item reexported as "_". + _ if self.inlining && (!is_pub || renamed == Some(kw::Underscore)) => {} + hir::ItemKind::GlobalAsm(..) => {} + hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} + hir::ItemKind::Use(path, kind) => { + for &res in &path.res { + // Struct and variant constructors and proc macro stubs always show up alongside + // their definitions, we've already processed them so just discard these. + if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { + continue; + } + + let attrs = + tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(item.owner_id.def_id)); + + // If there was a private module in the current path then don't bother inlining + // anything as it will probably be stripped anyway. + if is_pub && self.inside_public_path { + let please_inline = attrs.iter().any(|item| match item.meta_item_list() { + Some(ref list) if item.has_name(sym::doc) => { + list.iter().any(|i| i.has_name(sym::inline)) + } + _ => false, + }); + let is_glob = kind == hir::UseKind::Glob; + let ident = if is_glob { None } else { Some(name) }; + if self.maybe_inline_local( + item.owner_id.def_id, + res, + ident, + is_glob, + please_inline, + ) { + continue; + } + } + + self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)); + } + } + hir::ItemKind::Macro(ref macro_def, _) => { + // `#[macro_export] macro_rules!` items are handled separately in `visit()`, + // above, since they need to be documented at the module top level. Accordingly, + // we only want to handle macros if one of three conditions holds: + // + // 1. This macro was defined by `macro`, and thus isn't covered by the case + // above. + // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered + // by the case above. + // 3. We're inlining, since a reexport where inlining has been requested + // should be inlined even if it is also documented at the top level. + + let def_id = item.owner_id.to_def_id(); + let is_macro_2_0 = !macro_def.macro_rules; + let nonexported = !tcx.has_attr(def_id, sym::macro_export); + + if is_macro_2_0 || nonexported || self.inlining { + self.modules.last_mut().unwrap().items.push((item, renamed, None)); + } + } + hir::ItemKind::Mod(ref m) => { + self.enter_mod(item.owner_id.def_id, m, name); + } + hir::ItemKind::Fn(..) + | hir::ItemKind::ExternCrate(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::TyAlias(..) + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::Trait(..) + | hir::ItemKind::TraitAlias(..) => { + self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)) + } + hir::ItemKind::Const(..) => { + // Underscore constants do not correspond to a nameable item and + // so are never useful in documentation. + if name != kw::Underscore { + self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)); + } + } + hir::ItemKind::Impl(impl_) => { + // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick + // them up regardless of where they're located. + if !self.inlining && impl_.of_trait.is_none() { + self.modules.last_mut().unwrap().items.push((item, None, None)); + } + } + } + true + } + + fn visit_foreign_item_inner( + &mut self, + item: &'tcx hir::ForeignItem<'_>, + renamed: Option, + ) { + // If inlining we only want to include public functions. + if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() { + self.modules.last_mut().unwrap().foreigns.push((item, renamed)); + } + } + pub(crate) fn visit(mut self) -> Module<'tcx> { - let mut top_level_module = self.visit_mod_contents( - CRATE_DEF_ID, - self.cx.tcx.hir().root_module(), - self.cx.tcx.crate_name(LOCAL_CRATE), - None, - ); + let root_module = self.cx.tcx.hir().root_module(); + self.visit_mod_contents(CRATE_DEF_ID, root_module); + + let mut top_level_module = self.modules.pop().unwrap(); // `#[macro_export] macro_rules!` items are reexported at the top level of the // crate, regardless of where they're defined. We want to document the @@ -157,23 +381,33 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { top_level_module } - fn visit_mod_contents( - &mut self, - def_id: LocalDefId, - m: &'tcx hir::Mod<'tcx>, - name: Symbol, - parent_id: Option, - ) -> Module<'tcx> { - let mut om = Module::new(name, def_id, m.spans.inner_span); + /// This method will create a new module and push it onto the "modules stack" then call + /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead + /// add into the list of modules of the current module. + fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) { + self.modules.push(Module::new(name, id, m.spans.inner_span)); + + self.visit_mod_contents(id, m); + + let last = self.modules.pop().unwrap(); + self.modules.last_mut().unwrap().mods.push(last); + } + + /// This method will go through the given module items in two passes: + /// 1. The items which are not glob imports/reexports. + /// 2. The glob imports/reexports. + fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) { + debug!("Going through module {:?}", m); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public(); + + // Reimplementation of `walk_mod`: for &i in m.item_ids { let item = self.cx.tcx.hir().item(i); - if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - continue; + if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { + self.visit_item(item); } - self.visit_item(item, None, &mut om, parent_id); } for &i in m.item_ids { let item = self.cx.tcx.hir().item(i); @@ -181,227 +415,34 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // Later passes in rustdoc will de-duplicate by name and kind, so if glob- // imported items appear last, then they'll be the ones that get discarded. if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - self.visit_item(item, None, &mut om, parent_id); + self.visit_item(item); } } self.inside_public_path = orig_inside_public_path; - om - } - - /// Tries to resolve the target of a `pub use` statement and inlines the - /// target if it is defined locally and would not be documented otherwise, - /// or when it is specifically requested with `please_inline`. - /// (the latter is the case when the import is marked `doc(inline)`) - /// - /// Cross-crate inlining occurs later on during crate cleaning - /// and follows different rules. - /// - /// Returns `true` if the target has been inlined. - fn maybe_inline_local( - &mut self, - def_id: LocalDefId, - res: Res, - renamed: Option, - glob: bool, - om: &mut Module<'tcx>, - please_inline: bool, - ) -> bool { - debug!("maybe_inline_local res: {:?}", res); - - if self.cx.output_format.is_json() { - return false; - } - - let tcx = self.cx.tcx; - let Some(res_did) = res.opt_def_id() else { - return false; - }; - - let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); - // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. - let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline) - || tcx.is_doc_hidden(def_id.to_def_id()); - - // For cross-crate impl inlining we need to know whether items are - // reachable in documentation -- a previously unreachable item can be - // made reachable by cross-crate inlining which we're checking here. - // (this is done here because we need to know this upfront). - if !res_did.is_local() && !is_no_inline { - crate::visit_lib::lib_embargo_visit_item(self.cx, res_did); - return false; - } - - let Some(res_did) = res_did.as_local() else { - return false; - }; - - let is_private = !self - .cx - .cache - .effective_visibilities - .is_directly_public(self.cx.tcx, res_did.to_def_id()); - let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did); - - // Only inline if requested or if the item would otherwise be stripped. - if (!please_inline && !is_private && !is_hidden) || is_no_inline { - return false; - } - - if !self.view_item_stack.insert(res_did) { - return false; - } - - let ret = match tcx.hir().get_by_def_id(res_did) { - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { - let prev = mem::replace(&mut self.inlining, true); - for &i in m.item_ids { - let i = self.cx.tcx.hir().item(i); - self.visit_item(i, None, om, Some(def_id)); - } - self.inlining = prev; - true - } - Node::Item(it) if !glob => { - let prev = mem::replace(&mut self.inlining, true); - self.visit_item(it, renamed, om, Some(def_id)); - self.inlining = prev; - true - } - Node::ForeignItem(it) if !glob => { - let prev = mem::replace(&mut self.inlining, true); - self.visit_foreign_item(it, renamed, om); - self.inlining = prev; - true - } - _ => false, - }; - self.view_item_stack.remove(&res_did); - ret - } - - fn visit_item( - &mut self, - item: &'tcx hir::Item<'_>, - renamed: Option, - om: &mut Module<'tcx>, - parent_id: Option, - ) { - debug!("visiting item {:?}", item); - let name = renamed.unwrap_or(item.ident.name); - - let def_id = item.owner_id.to_def_id(); - let is_pub = self.cx.tcx.visibility(def_id).is_public(); - - if is_pub { - self.store_path(item.owner_id.to_def_id()); - } - - match item.kind { - hir::ItemKind::ForeignMod { items, .. } => { - for item in items { - let item = self.cx.tcx.hir().foreign_item(item.id); - self.visit_foreign_item(item, None, om); - } - } - // If we're inlining, skip private items or item reexported as "_". - _ if self.inlining && (!is_pub || renamed == Some(kw::Underscore)) => {} - hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} - hir::ItemKind::Use(path, kind) => { - for &res in &path.res { - // Struct and variant constructors and proc macro stubs always show up alongside - // their definitions, we've already processed them so just discard these. - if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { - continue; - } - - let attrs = self.cx.tcx.hir().attrs(item.hir_id()); - - // If there was a private module in the current path then don't bother inlining - // anything as it will probably be stripped anyway. - if is_pub && self.inside_public_path { - let please_inline = attrs.iter().any(|item| match item.meta_item_list() { - Some(ref list) if item.has_name(sym::doc) => { - list.iter().any(|i| i.has_name(sym::inline)) - } - _ => false, - }); - let is_glob = kind == hir::UseKind::Glob; - let ident = if is_glob { None } else { Some(name) }; - if self.maybe_inline_local( - item.owner_id.def_id, - res, - ident, - is_glob, - om, - please_inline, - ) { - continue; - } - } - - om.items.push((item, renamed, parent_id)) - } - } - hir::ItemKind::Macro(ref macro_def, _) => { - // `#[macro_export] macro_rules!` items are handled separately in `visit()`, - // above, since they need to be documented at the module top level. Accordingly, - // we only want to handle macros if one of three conditions holds: - // - // 1. This macro was defined by `macro`, and thus isn't covered by the case - // above. - // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered - // by the case above. - // 3. We're inlining, since a reexport where inlining has been requested - // should be inlined even if it is also documented at the top level. - - let def_id = item.owner_id.to_def_id(); - let is_macro_2_0 = !macro_def.macro_rules; - let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export); - - if is_macro_2_0 || nonexported || self.inlining { - om.items.push((item, renamed, None)); - } - } - hir::ItemKind::Mod(ref m) => { - om.mods.push(self.visit_mod_contents(item.owner_id.def_id, m, name, parent_id)); - } - hir::ItemKind::Fn(..) - | hir::ItemKind::ExternCrate(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Union(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::Static(..) - | hir::ItemKind::Trait(..) - | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)), - hir::ItemKind::Const(..) => { - // Underscore constants do not correspond to a nameable item and - // so are never useful in documentation. - if name != kw::Underscore { - om.items.push((item, renamed, parent_id)); - } - } - hir::ItemKind::Impl(impl_) => { - // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick - // them up regardless of where they're located. - if !self.inlining && impl_.of_trait.is_none() { - om.items.push((item, None, None)); - } - } - } - } - - fn visit_foreign_item( - &mut self, - item: &'tcx hir::ForeignItem<'_>, - renamed: Option, - om: &mut Module<'tcx>, - ) { - // If inlining we only want to include public functions. - if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() { - om.foreigns.push((item, renamed)); - } + } +} + +// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in +// such as impl blocks in const blocks. +impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.map + } + + fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { + let parent_id = if self.modules.len() > 1 { + Some(self.modules[self.modules.len() - 2].def_id) + } else { + None + }; + if self.visit_item_inner(i, None, parent_id) { + walk_item(self, i); + } + } + + fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) { + // handled in `visit_item_inner` } } From 3f057dd600d1db142c3bd50c7bf4ec220a35e45f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:02:39 +0100 Subject: [PATCH 011/137] Add regression test for impl blocks in const expr --- tests/rustdoc/impl-in-const-block.rs | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/rustdoc/impl-in-const-block.rs diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl-in-const-block.rs new file mode 100644 index 000000000000..b44e71352466 --- /dev/null +++ b/tests/rustdoc/impl-in-const-block.rs @@ -0,0 +1,43 @@ +// Regression test for #83026. +// The goal of this test is to ensure that impl blocks inside +// const expressions are documented as well. + +#![crate_name = "foo"] + +// @has 'foo/struct.A.html' +// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A' +// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)' +// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)' +// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()' +// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()' +pub struct A; + +const _: () = { + impl A { + const FOO: () = { + impl A { + pub fn woo(&self) {} + } + }; + + pub fn new() -> A { + A + } + } +}; +pub const X: () = { + impl A { + pub fn bar(&self) {} + } +}; + +fn foo() { + impl A { + pub fn yoo() {} + } + const _: () = { + impl A { + pub fn yuu() {} + } + }; +} From 3623613dc7384c7956b19f25be94538e310b9a77 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:02:46 +0100 Subject: [PATCH 012/137] Update newly failing UI tests --- .../infinite-recursive-type-impl-trait-return.rs | 4 +--- ...inite-recursive-type-impl-trait-return.stderr | 16 ++++++++++++++++ .../infinite-recursive-type-impl-trait.rs | 5 +---- .../infinite-recursive-type-impl-trait.stderr | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr create mode 100644 tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs index 4b1e04234c87..939da186fbcd 100644 --- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs +++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs @@ -1,12 +1,10 @@ -// check-pass // normalize-stderr-test: "`.*`" -> "`DEF_ID`" // normalize-stdout-test: "`.*`" -> "`DEF_ID`" // edition:2018 pub async fn f() -> impl std::fmt::Debug { - // rustdoc doesn't care that this is infinitely sized #[derive(Debug)] - enum E { + enum E { //~ ERROR This(E), Unit, } diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr new file mode 100644 index 000000000000..aff7402bc91c --- /dev/null +++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr @@ -0,0 +1,16 @@ +error[E0072]: recursive type `DEF_ID` has infinite size + --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5 + | +LL | enum E { + | ^^^^^^ +LL | This(E), + | - recursive without indirection + | +help: insert some indirection (e.g., a `DEF_ID`) to break the cycle + | +LL | This(Box), + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `DEF_ID`. diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs index ac79582fb3f0..ac5172574986 100644 --- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs +++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs @@ -1,8 +1,5 @@ -// check-pass - fn f() -> impl Sized { - // rustdoc doesn't care that this is infinitely sized - enum E { + enum E { //~ ERROR V(E), } unimplemented!() diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr new file mode 100644 index 000000000000..a61577bd14af --- /dev/null +++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr @@ -0,0 +1,16 @@ +error[E0072]: recursive type `f::E` has infinite size + --> $DIR/infinite-recursive-type-impl-trait.rs:2:5 + | +LL | enum E { + | ^^^^^^ +LL | V(E), + | - recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | V(Box), + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. From 9f70bdcbc88a51f6065dba37e033c2422dd263dc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:02:52 +0100 Subject: [PATCH 013/137] Improve code readability --- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/visit_ast.rs | 36 +++++++++++++--------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index bc8badad38eb..ca3e9916487a 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -138,7 +138,7 @@ pub(super) fn write_shared( Ok((ret, krates)) } - /// Read a file and return all lines that match the "{crate}":{data},\ format, + /// Read a file and return all lines that match the "{crate}":{data},\ format, /// and return a tuple `(Vec, Vec)`. /// /// This forms the payload of files that look like this: diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 2fbcda35e441..952304d40ecc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -192,6 +192,16 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ret } + #[inline] + fn add_to_current_mod( + &mut self, + item: &'tcx hir::Item<'_>, + renamed: Option, + parent_id: Option, + ) { + self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)) + } + fn visit_item_inner( &mut self, item: &'tcx hir::Item<'_>, @@ -253,7 +263,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)); + self.add_to_current_mod(item, renamed, parent_id); } } hir::ItemKind::Macro(ref macro_def, _) => { @@ -273,7 +283,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let nonexported = !tcx.has_attr(def_id, sym::macro_export); if is_macro_2_0 || nonexported || self.inlining { - self.modules.last_mut().unwrap().items.push((item, renamed, None)); + self.add_to_current_mod(item, renamed, None); } } hir::ItemKind::Mod(ref m) => { @@ -289,20 +299,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)) + self.add_to_current_mod(item, renamed, parent_id); } hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if name != kw::Underscore { - self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)); + self.add_to_current_mod(item, renamed, parent_id); } } hir::ItemKind::Impl(impl_) => { // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick // them up regardless of where they're located. if !self.inlining && impl_.of_trait.is_none() { - self.modules.last_mut().unwrap().items.push((item, None, None)); + self.add_to_current_mod(item, None, None); } } } @@ -339,15 +349,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // macro in the same module. let mut inserted = FxHashSet::default(); for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) { - if let Res::Def(DefKind::Macro(_), def_id) = export.res { - if let Some(local_def_id) = def_id.as_local() { - if self.cx.tcx.has_attr(def_id, sym::macro_export) { - if inserted.insert(def_id) { - let item = self.cx.tcx.hir().expect_item(local_def_id); - top_level_module.items.push((item, None, None)); - } - } - } + if let Res::Def(DefKind::Macro(_), def_id) = export.res && + let Some(local_def_id) = def_id.as_local() && + self.cx.tcx.has_attr(def_id, sym::macro_export) && + inserted.insert(def_id) + { + let item = self.cx.tcx.hir().expect_item(local_def_id); + top_level_module.items.push((item, None, None)); } } From 9b80a6ddf887dcbb2a8932741c6d711b7c475d9c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:02:57 +0100 Subject: [PATCH 014/137] Speed up execution a bit by removing some walks --- src/librustdoc/visit_ast.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 952304d40ecc..eccde86ff246 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -451,6 +451,26 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { } fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) { - // handled in `visit_item_inner` + // Handled in `visit_item_inner` + } + + fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) { + // Handled in `visit_item_inner` + } + + fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) { + // Handled in `visit_item_inner` + } + + fn visit_label(&mut self, _: &rustc_ast::Label) { + // Unneeded. + } + + fn visit_infer(&mut self, _: &hir::InferArg) { + // Unneeded. + } + + fn visit_lifetime(&mut self, _: &hir::Lifetime) { + // Unneeded. } } From 34685485c7c3dc001dd25ff1ba1db76694173a21 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2023 16:03:04 +0100 Subject: [PATCH 015/137] Improve code --- src/librustdoc/visit_ast.rs | 183 ++++++++++++++++++------------------ 1 file changed, 90 insertions(+), 93 deletions(-) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index eccde86ff246..c95ca6727b52 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet}; use rustc_hir::intravisit::{walk_item, Visitor}; use rustc_hir::{Node, CRATE_HIR_ID}; -use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{DefIdTree, TyCtxt}; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; @@ -74,7 +73,6 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> { inside_public_path: bool, exact_paths: DefIdMap>, modules: Vec>, - map: Map<'tcx>, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { @@ -87,7 +85,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { CRATE_DEF_ID, cx.tcx.hir().root_module().spans.inner_span, ); - let map = cx.tcx.hir(); RustdocVisitor { cx, @@ -96,7 +93,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { inside_public_path: true, exact_paths: Default::default(), modules: vec![om], - map, } } @@ -105,6 +101,94 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did)); } + pub(crate) fn visit(mut self) -> Module<'tcx> { + let root_module = self.cx.tcx.hir().root_module(); + self.visit_mod_contents(CRATE_DEF_ID, root_module); + + let mut top_level_module = self.modules.pop().unwrap(); + + // `#[macro_export] macro_rules!` items are reexported at the top level of the + // crate, regardless of where they're defined. We want to document the + // top level rexport of the macro, not its original definition, since + // the rexport defines the path that a user will actually see. Accordingly, + // we add the rexport as an item here, and then skip over the original + // definition in `visit_item()` below. + // + // We also skip `#[macro_export] macro_rules!` that have already been inserted, + // it can happen if within the same module a `#[macro_export] macro_rules!` + // is declared but also a reexport of itself producing two exports of the same + // macro in the same module. + let mut inserted = FxHashSet::default(); + for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) { + if let Res::Def(DefKind::Macro(_), def_id) = export.res && + let Some(local_def_id) = def_id.as_local() && + self.cx.tcx.has_attr(def_id, sym::macro_export) && + inserted.insert(def_id) + { + let item = self.cx.tcx.hir().expect_item(local_def_id); + top_level_module.items.push((item, None, None)); + } + } + + self.cx.cache.hidden_cfg = self + .cx + .tcx + .hir() + .attrs(CRATE_HIR_ID) + .iter() + .filter(|attr| attr.has_name(sym::doc)) + .flat_map(|attr| attr.meta_item_list().into_iter().flatten()) + .filter(|attr| attr.has_name(sym::cfg_hide)) + .flat_map(|attr| { + attr.meta_item_list() + .unwrap_or(&[]) + .iter() + .filter_map(|attr| { + Cfg::parse(attr.meta_item()?) + .map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg)) + .ok() + }) + .collect::>() + }) + .chain( + [Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)] + .into_iter(), + ) + .collect(); + + self.cx.cache.exact_paths = self.exact_paths; + top_level_module + } + + /// This method will go through the given module items in two passes: + /// 1. The items which are not glob imports/reexports. + /// 2. The glob imports/reexports. + fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) { + debug!("Going through module {:?}", m); + // Keep track of if there were any private modules in the path. + let orig_inside_public_path = self.inside_public_path; + self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public(); + + // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in + // the second loop): + for &i in m.item_ids { + let item = self.cx.tcx.hir().item(i); + if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { + self.visit_item(item); + } + } + for &i in m.item_ids { + let item = self.cx.tcx.hir().item(i); + // To match the way import precedence works, visit glob imports last. + // Later passes in rustdoc will de-duplicate by name and kind, so if glob- + // imported items appear last, then they'll be the ones that get discarded. + if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { + self.visit_item(item); + } + } + self.inside_public_path = orig_inside_public_path; + } + /// Tries to resolve the target of a `pub use` statement and inlines the /// target if it is defined locally and would not be documented otherwise, /// or when it is specifically requested with `please_inline`. @@ -197,7 +281,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &mut self, item: &'tcx hir::Item<'_>, renamed: Option, - parent_id: Option, + parent_id: Option, ) { self.modules.last_mut().unwrap().items.push((item, renamed, parent_id)) } @@ -330,65 +414,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub(crate) fn visit(mut self) -> Module<'tcx> { - let root_module = self.cx.tcx.hir().root_module(); - self.visit_mod_contents(CRATE_DEF_ID, root_module); - - let mut top_level_module = self.modules.pop().unwrap(); - - // `#[macro_export] macro_rules!` items are reexported at the top level of the - // crate, regardless of where they're defined. We want to document the - // top level rexport of the macro, not its original definition, since - // the rexport defines the path that a user will actually see. Accordingly, - // we add the rexport as an item here, and then skip over the original - // definition in `visit_item()` below. - // - // We also skip `#[macro_export] macro_rules!` that have already been inserted, - // it can happen if within the same module a `#[macro_export] macro_rules!` - // is declared but also a reexport of itself producing two exports of the same - // macro in the same module. - let mut inserted = FxHashSet::default(); - for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) { - if let Res::Def(DefKind::Macro(_), def_id) = export.res && - let Some(local_def_id) = def_id.as_local() && - self.cx.tcx.has_attr(def_id, sym::macro_export) && - inserted.insert(def_id) - { - let item = self.cx.tcx.hir().expect_item(local_def_id); - top_level_module.items.push((item, None, None)); - } - } - - self.cx.cache.hidden_cfg = self - .cx - .tcx - .hir() - .attrs(CRATE_HIR_ID) - .iter() - .filter(|attr| attr.has_name(sym::doc)) - .flat_map(|attr| attr.meta_item_list().into_iter().flatten()) - .filter(|attr| attr.has_name(sym::cfg_hide)) - .flat_map(|attr| { - attr.meta_item_list() - .unwrap_or(&[]) - .iter() - .filter_map(|attr| { - Cfg::parse(attr.meta_item()?) - .map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg)) - .ok() - }) - .collect::>() - }) - .chain( - [Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)] - .into_iter(), - ) - .collect(); - - self.cx.cache.exact_paths = self.exact_paths; - top_level_module - } - /// This method will create a new module and push it onto the "modules stack" then call /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead /// add into the list of modules of the current module. @@ -400,34 +425,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let last = self.modules.pop().unwrap(); self.modules.last_mut().unwrap().mods.push(last); } - - /// This method will go through the given module items in two passes: - /// 1. The items which are not glob imports/reexports. - /// 2. The glob imports/reexports. - fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) { - debug!("Going through module {:?}", m); - // Keep track of if there were any private modules in the path. - let orig_inside_public_path = self.inside_public_path; - self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public(); - - // Reimplementation of `walk_mod`: - for &i in m.item_ids { - let item = self.cx.tcx.hir().item(i); - if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - self.visit_item(item); - } - } - for &i in m.item_ids { - let item = self.cx.tcx.hir().item(i); - // To match the way import precedence works, visit glob imports last. - // Later passes in rustdoc will de-duplicate by name and kind, so if glob- - // imported items appear last, then they'll be the ones that get discarded. - if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - self.visit_item(item); - } - } - self.inside_public_path = orig_inside_public_path; - } } // We need to implement this visitor so it'll go everywhere and retrieve items we're interested in @@ -436,7 +433,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { - self.map + self.cx.tcx.hir() } fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { From 5b654a7e5eaa377bb75fee8dd20b8daba6d408dd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Jan 2023 20:40:25 +0100 Subject: [PATCH 016/137] Fix handling of items inside a `doc(hidden)` block --- src/librustdoc/clean/mod.rs | 16 +++---- src/librustdoc/passes/strip_hidden.rs | 68 +++++++++++++++++++++------ src/librustdoc/visit_ast.rs | 16 +++---- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3cb6ad10e72b..ee9d0e829f0f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2225,21 +2225,17 @@ fn clean_maybe_renamed_item<'tcx>( get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs); } - if !extra_attrs.is_empty() { + let mut item = if !extra_attrs.is_empty() { extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id)); let attrs = Attributes::from_ast(&extra_attrs); let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg); - vec![Item::from_def_id_and_attrs_and_parts( - def_id, - Some(name), - kind, - Box::new(attrs), - cfg, - )] + Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg) } else { - vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)] - } + Item::from_def_id_and_parts(def_id, Some(name), kind, cx) + }; + item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id()); + vec![item] }) } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index e07a788a72a4..cfd2171395ce 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -1,4 +1,6 @@ //! Strip all doc(hidden) items from the output. + +use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; use std::mem; @@ -7,6 +9,7 @@ use crate::clean::{Item, ItemIdSet, NestedAttributesExt}; use crate::core::DocContext; use crate::fold::{strip_item, DocFolder}; use crate::passes::{ImplStripper, Pass}; +use crate::visit_ast::inherits_doc_hidden; pub(crate) const STRIP_HIDDEN: Pass = Pass { name: "strip-hidden", @@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea // strip all #[doc(hidden)] items let krate = { - let mut stripper = Stripper { retained: &mut retained, update_retained: true }; + let mut stripper = Stripper { + retained: &mut retained, + update_retained: true, + tcx: cx.tcx, + is_in_hidden_item: false, + }; stripper.fold_crate(krate) }; @@ -36,14 +44,38 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea stripper.fold_crate(krate) } -struct Stripper<'a> { +struct Stripper<'a, 'tcx> { retained: &'a mut ItemIdSet, update_retained: bool, + tcx: TyCtxt<'tcx>, + is_in_hidden_item: bool, } -impl<'a> DocFolder for Stripper<'a> { +impl<'a, 'tcx> Stripper<'a, 'tcx> { + fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item { + let prev = self.is_in_hidden_item; + self.is_in_hidden_item |= is_in_hidden_item; + let ret = self.fold_item_recur(i); + self.is_in_hidden_item = prev; + ret + } +} + +impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { - if i.attrs.lists(sym::doc).has_word(sym::hidden) { + let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden); + let mut is_hidden = self.is_in_hidden_item || has_doc_hidden; + if !is_hidden && i.inline_stmt_id.is_none() { + // We don't need to check if it's coming from a reexport since the reexport itself was + // already checked. + is_hidden = i + .item_id + .as_def_id() + .and_then(|def_id| def_id.as_local()) + .map(|def_id| inherits_doc_hidden(self.tcx, def_id)) + .unwrap_or(false); + } + if is_hidden { debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); // Use a dedicated hidden item for fields, variants, and modules. // We need to keep private fields and variants, so that the docs @@ -53,23 +85,31 @@ impl<'a> DocFolder for Stripper<'a> { // module it's defined in. Both of these are marked "stripped," and // not included in the final docs, but since they still have an effect // on the final doc, cannot be completely removed from the Clean IR. - match *i.kind { + return match *i.kind { clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { // We need to recurse into stripped modules to // strip things like impl methods but when doing so // we must not add any items to the `retained` set. let old = mem::replace(&mut self.update_retained, false); - let ret = strip_item(self.fold_item_recur(i)); + let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i)); self.update_retained = old; - return Some(ret); + Some(ret) } - _ => return None, - } - } else { - if self.update_retained { - self.retained.insert(i.item_id); - } + _ => { + let ret = self.set_is_in_hidden_item_and_fold(true, i); + if has_doc_hidden { + // If the item itself has `#[doc(hidden)]`, then we simply remove it. + None + } else { + // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it. + Some(strip_item(ret)) + } + } + }; } - Some(self.fold_item_recur(i)) + if self.update_retained { + self.retained.insert(i.item_id); + } + Some(self.set_is_in_hidden_item_and_fold(is_hidden, i)) } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c95ca6727b52..2d2afb83f9dd 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -187,6 +187,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } self.inside_public_path = orig_inside_public_path; + debug!("Leaving module {:?}", m); } /// Tries to resolve the target of a `pub use` statement and inlines the @@ -290,7 +291,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &mut self, item: &'tcx hir::Item<'_>, renamed: Option, - parent_id: Option, + import_id: Option, ) -> bool { debug!("visiting item {:?}", item); let name = renamed.unwrap_or(item.ident.name); @@ -347,7 +348,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } } hir::ItemKind::Macro(ref macro_def, _) => { @@ -383,13 +384,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { | hir::ItemKind::Static(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if name != kw::Underscore { - self.add_to_current_mod(item, renamed, parent_id); + self.add_to_current_mod(item, renamed, import_id); } } hir::ItemKind::Impl(impl_) => { @@ -437,12 +438,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { } fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { - let parent_id = if self.modules.len() > 1 { - Some(self.modules[self.modules.len() - 2].def_id) - } else { - None - }; - if self.visit_item_inner(i, None, parent_id) { + if self.visit_item_inner(i, None, None) { walk_item(self, i); } } From c918efa6642c4ca6611068d09e7341731fd00a80 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Jan 2023 20:40:47 +0100 Subject: [PATCH 017/137] Update rustdoc/redirect test --- tests/rustdoc/redirect.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc/redirect.rs b/tests/rustdoc/redirect.rs index e3a14c7a74a0..5b7a76e1a773 100644 --- a/tests/rustdoc/redirect.rs +++ b/tests/rustdoc/redirect.rs @@ -9,9 +9,10 @@ pub trait Foo {} // @has redirect/index.html // @has - '//code' 'pub use reexp_stripped::Bar' // @has - '//code/a' 'Bar' +// @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar' // @has reexp_stripped/hidden/struct.Bar.html -// @has - '//p/a' '../../reexp_stripped/struct.Bar.html' // @has 'reexp_stripped/struct.Bar.html' +// @has - '//a[@href="struct.Bar.html"]' 'Bar' #[doc(no_inline)] pub use reexp_stripped::Bar; impl Foo for Bar {} From 4b3eef873407ab49918f941810e69c47c79a2b3c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Jan 2023 20:41:16 +0100 Subject: [PATCH 018/137] Add rustdoc test to ensure that items into a `doc(hidden)` block are handled as expected --- tests/rustdoc/hidden-private.rs | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/rustdoc/hidden-private.rs diff --git a/tests/rustdoc/hidden-private.rs b/tests/rustdoc/hidden-private.rs new file mode 100644 index 000000000000..834ba5231a1e --- /dev/null +++ b/tests/rustdoc/hidden-private.rs @@ -0,0 +1,50 @@ +// This is a regression test for . +// It ensures that the items in the `doc(hidden)` const block don't show up in the +// generated docs. + +// compile-flags: --document-private-items + +#![crate_name = "foo"] + +// @has 'foo/index.html' +// @count - '//*[@class="item-table"]//a[@class="struct"]' 2 +// @count - '//*[@class="item-table"]//a[@class="trait"]' 1 +// @count - '//*[@class="item-table"]//a[@class="macro"]' 0 +#[doc(hidden)] +const _: () = { + macro_rules! stry { + () => {}; + } + + struct ShouldBeHidden; + + // @has 'foo/struct.Foo.html' + // @!has - '//*[@class="code-header"]' 'impl Bar for Foo' + #[doc(hidden)] + impl Bar for Foo { + fn bar(&self) { + struct SHouldAlsoBeHidden; + } + } + + // @has 'foo/struct.Private.html' + // @has - '//*[@id="impl-Bar-for-Private"]/*[@class="code-header"]' 'impl Bar for Private' + // @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar(&self)' + impl Bar for Private { + fn bar(&self) {} + } + + // @has - '//*[@id="impl-Private"]/*[@class="code-header"]' 'impl Private' + // @has - '//*[@id="method.tralala"]/*[@class="code-header"]' 'fn tralala()' + impl Private { + fn tralala() {} + } +}; + + +struct Private; +pub struct Foo; + +pub trait Bar { + fn bar(&self); +} From ea844187b27fbcff521bcbcbe6615d51d0196fa2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Jan 2023 20:32:50 +0100 Subject: [PATCH 019/137] Special-case handling of impl blocks --- src/librustdoc/passes/strip_hidden.rs | 105 +++++++++++++++----------- src/librustdoc/visit_ast.rs | 18 ++++- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index cfd2171395ce..8c733ddefc0a 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -59,57 +59,74 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { self.is_in_hidden_item = prev; ret } + + /// In case `i` is a non-hidden impl block, then we special-case it by changing the value + /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility. + fn recurse_in_impl(&mut self, i: Item) -> Item { + let prev = mem::replace(&mut self.is_in_hidden_item, false); + let ret = self.fold_item_recur(i); + self.is_in_hidden_item = prev; + ret + } } impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden); - let mut is_hidden = self.is_in_hidden_item || has_doc_hidden; - if !is_hidden && i.inline_stmt_id.is_none() { - // We don't need to check if it's coming from a reexport since the reexport itself was - // already checked. - is_hidden = i - .item_id - .as_def_id() - .and_then(|def_id| def_id.as_local()) - .map(|def_id| inherits_doc_hidden(self.tcx, def_id)) - .unwrap_or(false); + let is_impl = matches!(*i.kind, clean::ImplItem(..)); + let mut is_hidden = has_doc_hidden; + if !is_impl { + is_hidden = self.is_in_hidden_item || has_doc_hidden; + if !is_hidden && i.inline_stmt_id.is_none() { + // We don't need to check if it's coming from a reexport since the reexport itself was + // already checked. + is_hidden = i + .item_id + .as_def_id() + .and_then(|def_id| def_id.as_local()) + .map(|def_id| inherits_doc_hidden(self.tcx, def_id)) + .unwrap_or(false); + } } - if is_hidden { - debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); - // Use a dedicated hidden item for fields, variants, and modules. - // We need to keep private fields and variants, so that the docs - // can show a placeholder "// some variants omitted". We need to keep - // private modules, because they can contain impl blocks, and impl - // block privacy is inherited from the type and trait, not from the - // module it's defined in. Both of these are marked "stripped," and - // not included in the final docs, but since they still have an effect - // on the final doc, cannot be completely removed from the Clean IR. - return match *i.kind { - clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { - // We need to recurse into stripped modules to - // strip things like impl methods but when doing so - // we must not add any items to the `retained` set. - let old = mem::replace(&mut self.update_retained, false); - let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i)); - self.update_retained = old; - Some(ret) + if !is_hidden { + if self.update_retained { + self.retained.insert(i.item_id); + } + return Some(if is_impl { + self.recurse_in_impl(i) + } else { + self.set_is_in_hidden_item_and_fold(false, i) + }); + } + debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); + // Use a dedicated hidden item for fields, variants, and modules. + // We need to keep private fields and variants, so that the docs + // can show a placeholder "// some variants omitted". We need to keep + // private modules, because they can contain impl blocks, and impl + // block privacy is inherited from the type and trait, not from the + // module it's defined in. Both of these are marked "stripped," and + // not included in the final docs, but since they still have an effect + // on the final doc, cannot be completely removed from the Clean IR. + match *i.kind { + clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { + // We need to recurse into stripped modules to + // strip things like impl methods but when doing so + // we must not add any items to the `retained` set. + let old = mem::replace(&mut self.update_retained, false); + let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i)); + self.update_retained = old; + Some(ret) + } + _ => { + let ret = self.set_is_in_hidden_item_and_fold(true, i); + if has_doc_hidden { + // If the item itself has `#[doc(hidden)]`, then we simply remove it. + None + } else { + // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it. + Some(strip_item(ret)) } - _ => { - let ret = self.set_is_in_hidden_item_and_fold(true, i); - if has_doc_hidden { - // If the item itself has `#[doc(hidden)]`, then we simply remove it. - None - } else { - // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it. - Some(strip_item(ret)) - } - } - }; + } } - if self.update_retained { - self.retained.insert(i.item_id); - } - Some(self.set_is_in_hidden_item_and_fold(is_hidden, i)) } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 2d2afb83f9dd..088cb3f33949 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -55,11 +55,21 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec { std::iter::once(crate_name).chain(relative).collect() } -pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: LocalDefId) -> bool { - while let Some(id) = tcx.opt_local_parent(node) { - node = id; - if tcx.is_doc_hidden(node.to_def_id()) { +pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool { + let hir = tcx.hir(); + while let Some(id) = tcx.opt_local_parent(def_id) { + def_id = id; + if tcx.is_doc_hidden(def_id.to_def_id()) { return true; + } else if let Some(node) = hir.find_by_def_id(def_id) && + matches!( + node, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }), + ) + { + // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly + // on them, they don't inherit it from the parent context. + return false; } } false From 42cc28ac8b7de426b4ae615242acd0be1bfa9a58 Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 31 Jan 2023 17:20:37 +0100 Subject: [PATCH 020/137] std: add type alias for raw OS errors Implement rust-lang/libs-team#173. --- library/std/src/io/error.rs | 19 +++++++++++++++---- library/std/src/io/error/repr_bitpacked.rs | 9 ++++++--- library/std/src/io/error/repr_unpacked.rs | 4 ++-- library/std/src/io/error/tests.rs | 2 +- library/std/src/io/mod.rs | 2 ++ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 3cabf24492ea..324d698eaeb1 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -88,12 +88,23 @@ impl From for Error { // doesn't accidentally get printed. #[cfg_attr(test, derive(Debug))] enum ErrorData { - Os(i32), + Os(RawOsError), Simple(ErrorKind), SimpleMessage(&'static SimpleMessage), Custom(C), } +/// The type of raw OS error codes returned by [`Error::raw_os_error`]. +/// +/// This is an [`i32`] on all currently supported platforms, but platforms +/// added in the future (such as UEFI) may use a different primitive type like +/// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum +/// portability. +/// +/// [`into`]: Into::into +#[unstable(feature = "raw_os_error_ty", issue = "none")] +pub type RawOsError = i32; + // `#[repr(align(4))]` is probably redundant, it should have that value or // higher already. We include it just because repr_bitpacked.rs's encoding // requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the @@ -579,7 +590,7 @@ impl Error { #[must_use] #[inline] pub fn last_os_error() -> Error { - Error::from_raw_os_error(sys::os::errno() as i32) + Error::from_raw_os_error(sys::os::errno()) } /// Creates a new instance of an [`Error`] from a particular OS error code. @@ -610,7 +621,7 @@ impl Error { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] - pub fn from_raw_os_error(code: i32) -> Error { + pub fn from_raw_os_error(code: RawOsError) -> Error { Error { repr: Repr::new_os(code) } } @@ -646,7 +657,7 @@ impl Error { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] - pub fn raw_os_error(&self) -> Option { + pub fn raw_os_error(&self) -> Option { match self.repr.data() { ErrorData::Os(i) => Some(i), ErrorData::Custom(..) => None, diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 3581484050dd..f94f88bac417 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -102,7 +102,7 @@ //! to use a pointer type to store something that may hold an integer, some of //! the time. -use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; +use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage}; use alloc::boxed::Box; use core::marker::PhantomData; use core::mem::{align_of, size_of}; @@ -172,7 +172,7 @@ impl Repr { } #[inline] - pub(super) fn new_os(code: i32) -> Self { + pub(super) fn new_os(code: RawOsError) -> Self { let utagged = ((code as usize) << 32) | TAG_OS; // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData); @@ -250,7 +250,7 @@ where let bits = ptr.as_ptr().addr(); match bits & TAG_MASK { TAG_OS => { - let code = ((bits as i64) >> 32) as i32; + let code = ((bits as i64) >> 32) as RawOsError; ErrorData::Os(code) } TAG_SIMPLE => { @@ -374,6 +374,9 @@ static_assert!((TAG_MASK + 1).is_power_of_two()); static_assert!(align_of::() >= TAG_MASK + 1); static_assert!(align_of::() >= TAG_MASK + 1); +// `RawOsError` must be an alias for `i32`. +const _: fn(RawOsError) -> i32 = |os| os; + static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE_MESSAGE, TAG_SIMPLE_MESSAGE); static_assert!(@usize_eq: TAG_MASK & TAG_CUSTOM, TAG_CUSTOM); static_assert!(@usize_eq: TAG_MASK & TAG_OS, TAG_OS); diff --git a/library/std/src/io/error/repr_unpacked.rs b/library/std/src/io/error/repr_unpacked.rs index d6ad55b99f5c..093fde33757e 100644 --- a/library/std/src/io/error/repr_unpacked.rs +++ b/library/std/src/io/error/repr_unpacked.rs @@ -2,7 +2,7 @@ //! non-64bit targets, where the packed 64 bit representation wouldn't work, and //! would have no benefit. -use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; +use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage}; use alloc::boxed::Box; type Inner = ErrorData>; @@ -18,7 +18,7 @@ impl Repr { Self(Inner::Custom(b)) } #[inline] - pub(super) fn new_os(code: i32) -> Self { + pub(super) fn new_os(code: RawOsError) -> Self { Self(Inner::Os(code)) } #[inline] diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 9aea62a5b940..36d52aef03cb 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -71,7 +71,7 @@ fn test_const() { #[test] fn test_os_packing() { - for code in -20i32..20i32 { + for code in -20..20 { let e = Error::from_raw_os_error(code); assert_eq!(e.raw_os_error(), Some(code)); assert_matches!( diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index de528e85368c..5907ba5d5fbf 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -262,6 +262,8 @@ use crate::sys_common::memchr; #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub use self::buffered::WriterPanicked; +#[unstable(feature = "raw_os_error_ty", issue = "none")] +pub use self::error::RawOsError; pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] From 05ee406cc83d5498b94873f949ee1de1bba2869f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Jan 2023 17:16:16 +0000 Subject: [PATCH 021/137] Add test. --- .../copy-prop/issue_107511.main.CopyProp.diff | 146 ++++++++++++++++++ tests/mir-opt/copy-prop/issue_107511.rs | 15 ++ 2 files changed, 161 insertions(+) create mode 100644 tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff create mode 100644 tests/mir-opt/copy-prop/issue_107511.rs diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff new file mode 100644 index 000000000000..7759e50e5585 --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff @@ -0,0 +1,146 @@ +- // MIR for `main` before CopyProp ++ // MIR for `main` after CopyProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue_107511.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/issue_107511.rs:+1:9: +1:16 + let _3: (); // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _4: std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _5: std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _6: usize; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _7: &[i32]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _8: &[i32; 4]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _10: (); // in scope 0 at $DIR/issue_107511.rs:+0:1: +11:2 + let _11: (); // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _12: std::option::Option; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _13: &mut std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _14: &mut std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _15: isize; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _16: !; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _18: i32; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + let _19: usize; // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19 + let mut _20: usize; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + let mut _21: bool; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + scope 1 { + debug sum => _1; // in scope 1 at $DIR/issue_107511.rs:+1:9: +1:16 + let _2: [i32; 4]; // in scope 1 at $DIR/issue_107511.rs:+2:9: +2:10 + scope 2 { + debug a => _2; // in scope 2 at $DIR/issue_107511.rs:+2:9: +2:10 + let mut _9: std::ops::Range; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + scope 3 { + debug iter => _9; // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + let _17: usize; // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + scope 4 { + debug i => _17; // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10 + } + } + scope 5 { + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue_107511.rs:+1:9: +1:16 + _1 = const 0_i32; // scope 0 at $DIR/issue_107511.rs:+1:19: +1:20 + StorageLive(_2); // scope 1 at $DIR/issue_107511.rs:+2:9: +2:10 + _2 = [const 0_i32, const 10_i32, const 20_i32, const 30_i32]; // scope 1 at $DIR/issue_107511.rs:+2:13: +2:28 +- StorageLive(_3); // scope 2 at $DIR/issue_107511.rs:+6:5: +8:6 + StorageLive(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_5); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_6); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + StorageLive(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + StorageLive(_8); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + _8 = &_2; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + _7 = move _8 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + StorageDead(_8); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18 + _6 = core::slice::::len(move _7) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + // mir::Constant + // + span: $DIR/issue_107511.rs:10:19: 10:22 + // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::::len}, val: Value() } + } + + bb1: { + StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 + Deinit(_5); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + (_5.0: usize) = const 0_usize; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + (_5.1: usize) = move _6; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 + _4 = as IntoIterator>::into_iter(move _5) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + // mir::Constant + // + span: $DIR/issue_107511.rs:10:14: 10:24 + // + literal: Const { ty: fn(std::ops::Range) -> as IntoIterator>::IntoIter { as IntoIterator>::into_iter}, val: Value() } + } + + bb2: { + StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 + StorageLive(_9); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + _9 = move _4; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 + } + + bb3: { +- StorageLive(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_14); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _14 = &mut _9; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _13 = &mut (*_14); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _12 = as Iterator>::next(move _13) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + // mir::Constant + // + span: $DIR/issue_107511.rs:10:14: 10:24 + // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } + } + + bb4: { + StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24 + _15 = discriminant(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + switchInt(move _15) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + } + + bb5: { + StorageLive(_17); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + _17 = ((_12 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- StorageLive(_19); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 +- _19 = _17; // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 + _20 = Len(_2); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- _21 = Lt(_19, _20); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- assert(move _21, "index out of bounds: the length is {} but the index is {}", move _20, _19) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ _21 = Lt(_17, _20); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ assert(move _21, "index out of bounds: the length is {} but the index is {}", move _20, _17) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 + } + + bb6: { + unreachable; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + } + + bb7: { +- _3 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 + StorageDead(_14); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_9); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_4); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 +- StorageDead(_3); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 + _0 = const (); // scope 0 at $DIR/issue_107511.rs:+0:11: +11:2 + StorageDead(_2); // scope 1 at $DIR/issue_107511.rs:+11:1: +11:2 + StorageDead(_1); // scope 0 at $DIR/issue_107511.rs:+11:1: +11:2 + return; // scope 0 at $DIR/issue_107511.rs:+11:2: +11:2 + } + + bb8: { +- _18 = _2[_19]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ _18 = _2[_17]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 + _1 = Add(_1, move _18); // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20 + StorageDead(_18); // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20 +- StorageDead(_19); // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21 +- _11 = const (); // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6 +- StorageDead(_17); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_14); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- _10 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 + goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 + } + } + diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs new file mode 100644 index 000000000000..0b872b89834a --- /dev/null +++ b/tests/mir-opt/copy-prop/issue_107511.rs @@ -0,0 +1,15 @@ +// unit-test: CopyProp + +// EMIT_MIR issue_107511.main.CopyProp.diff +fn main() { + let mut sum = 0; + let a = [0, 10, 20, 30]; + + // `i` is assigned in a loop. Only removing its `StorageDead` would mean that + // execution sees repeated `StorageLive`. This would be UB. + for i in 0..a.len() { + sum += a[i]; + } + + let _ = sum; +} From 3c10cf088a36c0799c9ee70e6d16efe6020da6d0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Jan 2023 16:49:01 +0000 Subject: [PATCH 022/137] Remove both StorageLive and StorageDead in CopyProp. --- compiler/rustc_mir_transform/src/copy_prop.rs | 25 +++++++++++-------- .../const_debuginfo.main.ConstDebugInfo.diff | 3 --- .../bad_op_mod_by_zero.main.ConstProp.diff | 1 - ...ar_literal_propagation.main.ConstProp.diff | 1 - .../copy-prop/cycle.main.CopyProp.diff | 2 +- .../dead_stores_79191.f.CopyProp.after.mir | 1 - .../dead_stores_better.f.CopyProp.after.mir | 1 - .../copy-prop/issue_107511.main.CopyProp.diff | 2 +- ...herit_overflow.main.DataflowConstProp.diff | 2 -- ...float_to_exponential_common.ConstProp.diff | 1 - .../mir-opt/issue_101973.inner.ConstProp.diff | 2 -- ...76432.test.SimplifyComparisonIntegral.diff | 1 - .../simplify_match.main.ConstProp.diff | 1 - ...filter.variant_a-{closure#0}.CopyProp.diff | 8 +++--- ..._a-{closure#0}.DestinationPropagation.diff | 4 --- ...filter.variant_b-{closure#0}.CopyProp.diff | 8 +++--- ..._b-{closure#0}.DestinationPropagation.diff | 4 --- .../try_identity_e2e.new.PreCodegen.after.mir | 4 --- .../try_identity_e2e.old.PreCodegen.after.mir | 2 -- 19 files changed, 24 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 182b3015dd7d..4c7d45be0753 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -162,17 +162,20 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) { - if let StatementKind::StorageDead(l) = stmt.kind - && self.storage_to_remove.contains(l) - { - stmt.make_nop(); - } else if let StatementKind::Assign(box (ref place, ref mut rvalue)) = stmt.kind - && place.as_local().is_some() - { - // Do not replace assignments. - self.visit_rvalue(rvalue, loc) - } else { - self.super_statement(stmt, loc); + match stmt.kind { + // When removing storage statements, we need to remove both (#107511). + StatementKind::StorageLive(l) | StatementKind::StorageDead(l) + if self.storage_to_remove.contains(l) => + { + stmt.make_nop() + } + StatementKind::Assign(box (ref place, ref mut rvalue)) + if place.as_local().is_some() => + { + // Do not replace assignments. + self.visit_rvalue(rvalue, loc) + } + _ => self.super_statement(stmt, loc), } } } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 5e587be1f165..4405b55875ed 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -56,11 +56,8 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/const_debuginfo.rs:+1:9: +1:10 _1 = const 1_u8; // scope 0 at $DIR/const_debuginfo.rs:+1:13: +1:16 - StorageLive(_2); // scope 1 at $DIR/const_debuginfo.rs:+2:9: +2:10 _2 = const 2_u8; // scope 1 at $DIR/const_debuginfo.rs:+2:13: +2:16 - StorageLive(_3); // scope 2 at $DIR/const_debuginfo.rs:+3:9: +3:10 _3 = const 3_u8; // scope 2 at $DIR/const_debuginfo.rs:+3:13: +3:16 StorageLive(_4); // scope 3 at $DIR/const_debuginfo.rs:+4:9: +4:12 StorageLive(_5); // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:20 diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff index e085a88b2da8..ae9ffd519a14 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff @@ -18,7 +18,6 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 _1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 - _4 = Eq(_1, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff index e3f5b120a323..22f710387db7 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff @@ -11,7 +11,6 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 _1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 - _2 = consume(_1) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff index bc5083e1ad01..3e61869e82f1 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff @@ -29,7 +29,7 @@ } bb1: { - StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10 +- StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10 _2 = _1; // scope 1 at $DIR/cycle.rs:+2:13: +2:14 - StorageLive(_3); // scope 2 at $DIR/cycle.rs:+3:9: +3:10 - _3 = _2; // scope 2 at $DIR/cycle.rs:+3:13: +3:14 diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir index 918817da56ce..d48b04e2de27 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir @@ -11,7 +11,6 @@ fn f(_1: usize) -> usize { } bb0: { - StorageLive(_2); // scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10 _2 = _1; // scope 0 at $DIR/dead_stores_79191.rs:+1:13: +1:14 _1 = const 5_usize; // scope 1 at $DIR/dead_stores_79191.rs:+2:5: +2:10 _1 = _2; // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10 diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir index cf21fadd4379..727791f50a4e 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir @@ -11,7 +11,6 @@ fn f(_1: usize) -> usize { } bb0: { - StorageLive(_2); // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10 _2 = _1; // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14 _1 = const 5_usize; // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10 _1 = _2; // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10 diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff index 7759e50e5585..a9a0830e55c5 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff @@ -98,7 +98,7 @@ } bb5: { - StorageLive(_17); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 +- StorageLive(_17); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 _17 = ((_12 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 - StorageLive(_19); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff index 6870d7d6c45b..9c3f87f47c12 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff @@ -16,9 +16,7 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 _1 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 _2 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 _5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index df9f8dcf1a40..7c5d28069d59 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -79,7 +79,6 @@ } bb6: { - StorageLive(_10); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26 _10 = ((_7 as Some).0: usize); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26 StorageLive(_11); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46 _11 = &mut (*_1); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46 diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff index 30bf2c0684e5..002392c5cf81 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff @@ -33,7 +33,6 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65 StorageLive(_3); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58 - StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17 StorageLive(_12); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 StorageLive(_13); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 _14 = CheckedShr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 @@ -63,7 +62,6 @@ StorageDead(_13); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 _4 = BitOr(const 0_u32, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27 StorageDead(_12); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 - StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 _10 = CheckedShr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index c14780052fb0..cc4f7cc06991 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -29,7 +29,6 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/issue_76432.rs:+1:9: +1:10 - StorageLive(_4); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29 StorageLive(_5); // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29 _5 = [_1, _1, _1]; // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29 _4 = &_5; // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29 diff --git a/tests/mir-opt/simplify_match.main.ConstProp.diff b/tests/mir-opt/simplify_match.main.ConstProp.diff index 35ffc4963cb6..b700adfb105b 100644 --- a/tests/mir-opt/simplify_match.main.ConstProp.diff +++ b/tests/mir-opt/simplify_match.main.ConstProp.diff @@ -10,7 +10,6 @@ } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_match.rs:+1:17: +1:18 _2 = const false; // scope 0 at $DIR/simplify_match.rs:+1:21: +1:26 - switchInt(_2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31 + switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31 diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff index d1f6fd97dc7c..da6389676f0d 100644 --- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff +++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff @@ -101,16 +101,16 @@ } bb0: { - StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 +- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 _25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 _3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 - StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 +- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 _26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 _4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 - StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 +- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 _27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 _5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 - StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 +- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 _28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 _6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56 diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff index 259cd4118960..294c3272f4f1 100644 --- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff +++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff @@ -85,16 +85,12 @@ } bb0: { - StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 _25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 _3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28 - StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 _26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 _4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31 - StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 _27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 _5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34 - StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 _28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 _6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37 - StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56 diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff index c3b8e7d2eba2..5e4bdbdfa2e2 100644 --- a/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff +++ b/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff @@ -33,16 +33,16 @@ } bb0: { - StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 +- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 _21 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 _3 = ((*_21).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 - StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 +- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 _22 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 _4 = ((*_22).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 - StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 +- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 _23 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 _5 = ((*_23).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 - StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 +- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 _24 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 _6 = ((*_24).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58 diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff index a43e84d29c7a..45af6600cd4e 100644 --- a/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff +++ b/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff @@ -25,16 +25,12 @@ } bb0: { - StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 _13 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 _3 = ((*_13).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30 - StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 _14 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 _4 = ((*_14).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33 - StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 _15 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 _5 = ((*_15).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36 - StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 _16 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 _6 = ((*_16).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39 - StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58 diff --git a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir index 7c67d2abcf7c..a4d2660ca6ae 100644 --- a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir +++ b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir @@ -30,7 +30,6 @@ fn new(_1: Result) -> Result { } bb1: { - StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 _5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 Deinit(_2); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 ((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 @@ -40,7 +39,6 @@ fn new(_1: Result) -> Result { } bb2: { - StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 _4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 Deinit(_2); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 @@ -50,7 +48,6 @@ fn new(_1: Result) -> Result { } bb3: { - StorageLive(_8); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 _8 = move ((_2 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 ((_0 as Err).0: E) = move _8; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 @@ -64,7 +61,6 @@ fn new(_1: Result) -> Result { } bb5: { - StorageLive(_7); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 _7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 ((_0 as Ok).0: T) = move _7; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 diff --git a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir index 4a838e140262..37851c66a607 100644 --- a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir +++ b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir @@ -19,7 +19,6 @@ fn old(_1: Result) -> Result { } bb1: { - StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 _4 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 ((_0 as Err).0: E) = move _4; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 @@ -32,7 +31,6 @@ fn old(_1: Result) -> Result { } bb3: { - StorageLive(_3); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 _3 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 ((_0 as Ok).0: T) = move _3; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 From e8ac0404bdff209b9c542e772bf391800924ebf8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Jan 2023 18:07:57 +0000 Subject: [PATCH 023/137] Remove assignment. --- .../copy-prop/issue_107511.main.CopyProp.diff | 146 +++++++++--------- tests/mir-opt/copy-prop/issue_107511.rs | 2 - 2 files changed, 70 insertions(+), 78 deletions(-) diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff index a9a0830e55c5..28ba651ad4ae 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff @@ -4,38 +4,35 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_107511.rs:+0:11: +0:11 let mut _1: i32; // in scope 0 at $DIR/issue_107511.rs:+1:9: +1:16 - let _3: (); // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _3: std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 let mut _4: std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 - let mut _5: std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 - let mut _6: usize; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 - let mut _7: &[i32]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 - let mut _8: &[i32; 4]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 - let mut _10: (); // in scope 0 at $DIR/issue_107511.rs:+0:1: +11:2 - let _11: (); // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 - let mut _12: std::option::Option; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _5: usize; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _6: &[i32]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _7: &[i32; 4]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24 + let mut _9: (); // in scope 0 at $DIR/issue_107511.rs:+0:1: +9:2 + let _10: (); // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _11: std::option::Option; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _12: &mut std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 let mut _13: &mut std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 - let mut _14: &mut std::ops::Range; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24 - let mut _15: isize; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 - let mut _16: !; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 - let mut _18: i32; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 - let _19: usize; // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19 - let mut _20: usize; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 - let mut _21: bool; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + let mut _14: isize; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _15: !; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6 + let mut _17: i32; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + let _18: usize; // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19 + let mut _19: usize; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 + let mut _20: bool; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20 scope 1 { debug sum => _1; // in scope 1 at $DIR/issue_107511.rs:+1:9: +1:16 let _2: [i32; 4]; // in scope 1 at $DIR/issue_107511.rs:+2:9: +2:10 scope 2 { debug a => _2; // in scope 2 at $DIR/issue_107511.rs:+2:9: +2:10 - let mut _9: std::ops::Range; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + let mut _8: std::ops::Range; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 scope 3 { - debug iter => _9; // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - let _17: usize; // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + debug iter => _8; // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + let _16: usize; // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 scope 4 { - debug i => _17; // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10 + debug i => _16; // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10 } } - scope 5 { - } } } @@ -44,70 +41,69 @@ _1 = const 0_i32; // scope 0 at $DIR/issue_107511.rs:+1:19: +1:20 StorageLive(_2); // scope 1 at $DIR/issue_107511.rs:+2:9: +2:10 _2 = [const 0_i32, const 10_i32, const 20_i32, const 30_i32]; // scope 1 at $DIR/issue_107511.rs:+2:13: +2:28 -- StorageLive(_3); // scope 2 at $DIR/issue_107511.rs:+6:5: +8:6 + StorageLive(_3); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 StorageLive(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - StorageLive(_5); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_5); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 StorageLive(_6); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 StorageLive(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 - StorageLive(_8); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 - _8 = &_2; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 - _7 = move _8 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 - StorageDead(_8); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18 - _6 = core::slice::::len(move _7) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + _7 = &_2; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + _6 = move _7 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 + StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18 + _5 = core::slice::::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 // mir::Constant // + span: $DIR/issue_107511.rs:10:19: 10:22 // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::::len}, val: Value() } } bb1: { - StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 - Deinit(_5); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - (_5.0: usize) = const 0_usize; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - (_5.1: usize) = move _6; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 - _4 = as IntoIterator>::into_iter(move _5) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + Deinit(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + (_4.0: usize) = const 0_usize; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + (_4.1: usize) = move _5; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 + _3 = as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 // mir::Constant // + span: $DIR/issue_107511.rs:10:14: 10:24 // + literal: Const { ty: fn(std::ops::Range) -> as IntoIterator>::IntoIter { as IntoIterator>::into_iter}, val: Value() } } bb2: { - StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 - StorageLive(_9); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - _9 = move _4; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageDead(_4); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 + StorageLive(_8); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + _8 = move _3; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 } bb3: { -- StorageLive(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 +- StorageLive(_10); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageLive(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 StorageLive(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 StorageLive(_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - StorageLive(_14); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - _14 = &mut _9; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - _13 = &mut (*_14); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - _12 = as Iterator>::next(move _13) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _13 = &mut _8; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _12 = &mut (*_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + _11 = as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 // mir::Constant // + span: $DIR/issue_107511.rs:10:14: 10:24 // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } } bb4: { - StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24 - _15 = discriminant(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 - switchInt(move _15) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24 + _14 = discriminant(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 + switchInt(move _14) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 } bb5: { -- StorageLive(_17); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 - _17 = ((_12 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 - StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -- StorageLive(_19); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 -- _19 = _17; // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 - _20 = Len(_2); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -- _21 = Lt(_19, _20); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -- assert(move _21, "index out of bounds: the length is {} but the index is {}", move _20, _19) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -+ _21 = Lt(_17, _20); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -+ assert(move _21, "index out of bounds: the length is {} but the index is {}", move _20, _17) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- StorageLive(_16); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + _16 = ((_11 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10 + StorageLive(_17); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 +- _18 = _16; // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19 + _19 = Len(_2); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- _20 = Lt(_18, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 +- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ _20 = Lt(_16, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 } bb6: { @@ -115,31 +111,29 @@ } bb7: { -- _3 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 - StorageDead(_14); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 - StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 -- StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 - StorageDead(_9); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 - StorageDead(_4); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 -- StorageDead(_3); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 - _0 = const (); // scope 0 at $DIR/issue_107511.rs:+0:11: +11:2 - StorageDead(_2); // scope 1 at $DIR/issue_107511.rs:+11:1: +11:2 - StorageDead(_1); // scope 0 at $DIR/issue_107511.rs:+11:1: +11:2 - return; // scope 0 at $DIR/issue_107511.rs:+11:2: +11:2 + _0 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 + StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_8); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_3); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_2); // scope 1 at $DIR/issue_107511.rs:+9:1: +9:2 + StorageDead(_1); // scope 0 at $DIR/issue_107511.rs:+9:1: +9:2 + return; // scope 0 at $DIR/issue_107511.rs:+9:2: +9:2 } bb8: { -- _18 = _2[_19]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 -+ _18 = _2[_17]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 - _1 = Add(_1, move _18); // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20 - StorageDead(_18); // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20 -- StorageDead(_19); // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21 -- _11 = const (); // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6 -- StorageDead(_17); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 - StorageDead(_14); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 - StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 -- StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 -- _10 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 +- _17 = _2[_18]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 ++ _17 = _2[_16]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20 + _1 = Add(_1, move _17); // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20 + StorageDead(_17); // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20 +- StorageDead(_18); // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21 +- _10 = const (); // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6 +- StorageDead(_16); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 + StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6 +- _9 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6 } } diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs index 0b872b89834a..d593f2872ea4 100644 --- a/tests/mir-opt/copy-prop/issue_107511.rs +++ b/tests/mir-opt/copy-prop/issue_107511.rs @@ -10,6 +10,4 @@ fn main() { for i in 0..a.len() { sum += a[i]; } - - let _ = sum; } From 2c23c7f0cd7a665bbd7b173ebfc26cae223304e3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 31 Jan 2023 20:43:18 +0000 Subject: [PATCH 024/137] Erase regions before uninhabited check --- compiler/rustc_borrowck/src/type_check/mod.rs | 5 ++++- tests/ui/uninhabited/issue-107505.rs | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/ui/uninhabited/issue-107505.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 06087b0c579d..0a78bc0030be 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1484,7 +1484,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } None => { - if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) { + // The signature in this call can reference region variables, + // so erase them before calling a query. + let output_ty = self.tcx().erase_regions(sig.output()); + if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/tests/ui/uninhabited/issue-107505.rs b/tests/ui/uninhabited/issue-107505.rs new file mode 100644 index 000000000000..61598541ddf0 --- /dev/null +++ b/tests/ui/uninhabited/issue-107505.rs @@ -0,0 +1,18 @@ +// compile-flags: --crate-type=lib +// check-pass + +// Make sure we don't pass inference variables to uninhabitedness checks in borrowck + +struct Command<'s> { + session: &'s (), + imp: std::convert::Infallible, +} + +fn command(_: &()) -> Command<'_> { + unreachable!() +} + +fn with_session<'s>(a: &std::process::Command, b: &'s ()) -> Command<'s> { + a.get_program(); + command(b) +} From 5e90940a4b742e7f1e86f21c26b56e99a8733458 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 31 Jan 2023 18:13:57 -0800 Subject: [PATCH 025/137] Enable Cargo's sparse protocol in CI --- .github/workflows/ci.yml | 3 +++ src/ci/github-actions/ci.yml | 1 + src/ci/run.sh | 2 ++ 3 files changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 552680f06f66..17d8ffc7e635 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,7 @@ jobs: name: PR env: CI_JOB_NAME: "${{ matrix.name }}" + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse SCCACHE_BUCKET: rust-lang-ci-sccache2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" CACHE_DOMAIN: ci-caches.rust-lang.org @@ -162,6 +163,7 @@ jobs: name: auto env: CI_JOB_NAME: "${{ matrix.name }}" + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" @@ -584,6 +586,7 @@ jobs: name: try env: CI_JOB_NAME: "${{ matrix.name }}" + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5e676a470a03..dc09c1201990 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -33,6 +33,7 @@ x--expand-yaml-anchors--remove: - &shared-ci-variables CI_JOB_NAME: ${{ matrix.name }} + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - &public-variables SCCACHE_BUCKET: rust-lang-ci-sccache2 diff --git a/src/ci/run.sh b/src/ci/run.sh index 0db9c993eecb..93dccb54c4e3 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -45,6 +45,8 @@ fi ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" +export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse + if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" From 679dde7338281f958094b409202cc23ce1ba640c Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Feb 2023 05:55:48 +0000 Subject: [PATCH 026/137] fix parser mistaking const closures for const item --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 21 ++++++++++++++----- tests/ui/parser/recover-quantified-closure.rs | 2 +- .../parser/recover-quantified-closure.stderr | 4 ++-- .../const-closure-parse-not-item.rs | 10 +++++++++ 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index dcc3059a7f44..701a2a3efcf2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2108,7 +2108,7 @@ impl<'a> Parser<'a> { ClosureBinder::NotPresent }; - let constness = self.parse_constness(Case::Sensitive); + let constness = self.parse_closure_constness(Case::Sensitive); let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ffb23b50a160..bb06ad20118d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -739,9 +739,10 @@ impl<'a> Parser<'a> { fn check_const_closure(&self) -> bool { self.is_keyword_ahead(0, &[kw::Const]) && self.look_ahead(1, |t| match &t.kind { - token::Ident(kw::Move | kw::Static | kw::Async, _) - | token::OrOr - | token::BinOp(token::Or) => true, + // async closures do not work with const closures, so we do not parse that here. + token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => { + true + } _ => false, }) } @@ -1203,8 +1204,18 @@ impl<'a> Parser<'a> { /// Parses constness: `const` or nothing. fn parse_constness(&mut self, case: Case) -> Const { - // Avoid const blocks to be parsed as const items - if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) + self.parse_constness_(case, false) + } + + /// Parses constness for closures + fn parse_closure_constness(&mut self, case: Case) -> Const { + self.parse_constness_(case, true) + } + + fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const { + // Avoid const blocks and const closures to be parsed as const items + if (self.check_const_closure() == is_closure) + && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace)) && self.eat_keyword_case(kw::Const, case) { Const::Yes(self.prev_token.uninterpolated_span()) diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs index df22f5e065c8..10af39b70074 100644 --- a/tests/ui/parser/recover-quantified-closure.rs +++ b/tests/ui/parser/recover-quantified-closure.rs @@ -7,6 +7,6 @@ fn main() { enum Foo { Bar } fn foo(x: impl Iterator) { for ::Bar in x {} - //~^ ERROR expected one of `const`, `move`, `static`, `|` + //~^ ERROR expected one of `move`, `static`, `|` //~^^ ERROR `for<...>` binders for closures are experimental } diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr index 9ec4d2c034d0..39eec80f658a 100644 --- a/tests/ui/parser/recover-quantified-closure.stderr +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -1,8 +1,8 @@ -error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::` +error: expected one of `move`, `static`, `|`, or `||`, found `::` --> $DIR/recover-quantified-closure.rs:9:14 | LL | for ::Bar in x {} - | ^^ expected one of `const`, `move`, `static`, `|`, or `||` + | ^^ expected one of `move`, `static`, `|`, or `||` error[E0658]: `for<...>` binders for closures are experimental --> $DIR/recover-quantified-closure.rs:2:5 diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs new file mode 100644 index 000000000000..2c99d8bf1c67 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_trait_impl, const_closures)] +#![allow(incomplete_features)] + +const fn test() -> impl ~const Fn() { + const move || {} +} + +fn main() {} From 5fd4f5bceb456bd3681381bb390562466fdc4356 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 27 Jan 2023 20:45:03 +0100 Subject: [PATCH 027/137] Add candidates for DiscriminantKind builtin --- .../src/solve/assembly.rs | 8 ++++++++ .../src/solve/project_goals.rs | 20 +++++++++++++++++++ .../src/solve/trait_goals.rs | 8 ++++++++ 3 files changed, 36 insertions(+) diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 5690b6536bbc..ccdf6246083c 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -81,6 +81,7 @@ pub(super) enum CandidateSource { AliasBound, } +/// Methods used to assemble candidates for either trait or projection goals. pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { fn self_ty(self) -> Ty<'tcx>; @@ -188,6 +189,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec>; + + fn consider_builtin_discriminant_kind_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -320,6 +326,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_generator_candidate(self, goal) } else if lang_items.unsize_trait() == Some(trait_def_id) { G::consider_builtin_unsize_candidate(self, goal) + } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) { + G::consider_builtin_discriminant_kind_candidate(self, goal) } else { Err(NoSolution) }; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index a23fdd24b4e4..48627ee6096f 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -581,6 +581,26 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ) -> Vec> { bug!("`Unsize` does not have an associated type: {:?}", goal); } + + fn consider_builtin_discriminant_kind_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let self_ty = goal.predicate.self_ty(); + + let tcx = ecx.tcx(); + let term = self_ty.discriminant_ty(tcx).into(); + + Self::consider_assumption( + ecx, + goal, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(goal.predicate.def_id(), [self_ty]), + term, + }) + .to_predicate(tcx), + ) + } } /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 29ee9da38e08..0003dfeaee78 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -439,6 +439,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { responses } + + fn consider_builtin_discriminant_kind_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + _goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + // `DiscriminantKind` is automatically implemented for every type. + ecx.make_canonical_response(Certainty::Yes) + } } impl<'tcx> EvalCtxt<'_, 'tcx> { From de50a86a12d6db76e7fec4c8f15e17ae199acb7e Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Wed, 1 Feb 2023 17:13:57 +0100 Subject: [PATCH 028/137] Simplify discriminant_kind goal using new helper function --- .../src/solve/project_goals.rs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 48627ee6096f..170b560d7b6a 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -586,20 +586,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { - let self_ty = goal.predicate.self_ty(); - - let tcx = ecx.tcx(); - let term = self_ty.discriminant_ty(tcx).into(); - - Self::consider_assumption( - ecx, - goal, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(goal.predicate.def_id(), [self_ty]), - term, - }) - .to_predicate(tcx), - ) + let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx()); + let nested_goals = ecx.infcx.eq( + goal.param_env, + goal.predicate.term.ty().expect("expected ty goal"), + discriminant, + )?; + ecx.evaluate_all_and_make_canonical_response(nested_goals) } } From 4bce0751492a3e08ac6f4998e06b4dfa72943cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 1 Feb 2023 17:50:11 +0100 Subject: [PATCH 029/137] Dynamically align values in staged build timer table to avoid overflow --- src/ci/stage-build.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py index c373edfcf46a..7421ea3f6597 100644 --- a/src/ci/stage-build.py +++ b/src/ci/stage-build.py @@ -234,18 +234,27 @@ class Timer: def print_stats(self): total_duration = sum(self.stages.values()) - # 57 is the width of the whole table - divider = "-" * 57 + total_duration_label = "Total duration:" + + # 1 is for ":", 2 is horizontal space + max_label_length = max(16, max( + len(label) for label in list(self.stages.keys()) + [total_duration_label[:-1]] + )) + 1 + 2 + + table_width = max_label_length + 24 + divider = "-" * table_width with StringIO() as output: print(divider, file=output) for (name, duration) in self.stages.items(): pct = (duration / total_duration) * 100 name_str = f"{name}:" - print(f"{name_str:<34} {duration:>12.2f}s ({pct:>5.2f}%)", file=output) + print(f"{name_str:<{max_label_length}} {duration:>12.2f}s ({pct:>5.2f}%)", + file=output) - total_duration_label = "Total duration:" - print(f"{total_duration_label:<34} {total_duration:>12.2f}s", file=output) + print(file=output) + print(f"{total_duration_label:<{max_label_length}} {total_duration:>12.2f}s", + file=output) print(divider, file=output, end="") LOGGER.info(f"Timer results\n{output.getvalue()}") From 7bd8fbbd28f38669bc83cb734e2ffef44f3de9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 1 Feb 2023 17:50:38 +0100 Subject: [PATCH 030/137] Print total duration in human time --- src/ci/stage-build.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py index 7421ea3f6597..775478bcbab4 100644 --- a/src/ci/stage-build.py +++ b/src/ci/stage-build.py @@ -241,7 +241,7 @@ class Timer: len(label) for label in list(self.stages.keys()) + [total_duration_label[:-1]] )) + 1 + 2 - table_width = max_label_length + 24 + table_width = max_label_length + 23 divider = "-" * table_width with StringIO() as output: @@ -253,7 +253,7 @@ class Timer: file=output) print(file=output) - print(f"{total_duration_label:<{max_label_length}} {total_duration:>12.2f}s", + print(f"{total_duration_label:<{max_label_length}} {humantime(total_duration):>22}", file=output) print(divider, file=output, end="") LOGGER.info(f"Timer results\n{output.getvalue()}") @@ -274,6 +274,21 @@ def change_cwd(dir: Path): os.chdir(cwd) +def humantime(time_s: int) -> str: + hours = time_s // 3600 + time_s = time_s % 3600 + minutes = time_s // 60 + seconds = time_s % 60 + + result = "" + if hours > 0: + result += f"{int(hours)}h " + if minutes > 0: + result += f"{int(minutes)}m " + result += f"{round(seconds)}s" + return result + + def move_path(src: Path, dst: Path): LOGGER.info(f"Moving `{src}` to `{dst}`") shutil.move(src, dst) From a9c8a5c0255d056f78f1347c431fd88bc727febb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 1 Feb 2023 20:26:05 +0400 Subject: [PATCH 031/137] ast: Optimize list and value extraction primitives for attributes It's not necessary to convert the whole attribute into a meta item to extract something specific --- compiler/rustc_ast/src/ast.rs | 7 ++ compiler/rustc_ast/src/attr/mod.rs | 66 +++++++++----- .../rustc_codegen_ssa/src/codegen_attrs.rs | 88 ++++++++----------- compiler/rustc_passes/src/lib_features.rs | 5 +- 4 files changed, 90 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8ad3270c5103..f2258fecfeaf 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1826,6 +1826,13 @@ pub enum LitKind { } impl LitKind { + pub fn str(&self) -> Option { + match *self { + LitKind::Str(s, _) => Some(s), + _ => None, + } + } + /// Returns `true` if this literal is a string. pub fn is_str(&self) -> bool { matches!(self, LitKind::Str(..)) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index c6b6207b3186..cd60506dd807 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -140,17 +140,14 @@ impl Attribute { pub fn value_str(&self) -> Option { match &self.kind { - AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()), + AttrKind::Normal(normal) => normal.item.value_str(), AttrKind::DocComment(..) => None, } } pub fn meta_item_list(&self) -> Option> { match &self.kind { - AttrKind::Normal(normal) => match normal.item.meta_kind() { - Some(MetaItemKind::List(list)) => Some(list), - _ => None, - }, + AttrKind::Normal(normal) => normal.item.meta_item_list(), AttrKind::DocComment(..) => None, } } @@ -216,6 +213,20 @@ impl MetaItem { } } +impl AttrArgsEq { + fn value_str(&self) -> Option { + match self { + AttrArgsEq::Ast(expr) => match expr.kind { + ExprKind::Lit(token_lit) => { + LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str()) + } + _ => None, + }, + AttrArgsEq::Hir(lit) => lit.kind.str(), + } + } +} + impl AttrItem { pub fn span(&self) -> Span { self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span)) @@ -228,6 +239,22 @@ impl AttrItem { pub fn meta_kind(&self) -> Option { MetaItemKind::from_attr_args(&self.args) } + + fn meta_item_list(&self) -> Option> { + match &self.args { + AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => { + MetaItemKind::list_from_tokens(args.tokens.clone()) + } + AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None, + } + } + + fn value_str(&self) -> Option { + match &self.args { + AttrArgs::Eq(_, args) => args.value_str(), + AttrArgs::Delimited(_) | AttrArgs::Empty => None, + } + } } impl Attribute { @@ -247,13 +274,11 @@ impl Attribute { /// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`. /// * `#[doc(...)]` returns `None`. pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> { - match self.kind { - AttrKind::DocComment(kind, data) => Some((data, kind)), - AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal - .item - .meta_kind() - .and_then(|kind| kind.value_str()) - .map(|data| (data, CommentKind::Line)), + match &self.kind { + AttrKind::DocComment(kind, data) => Some((*data, *kind)), + AttrKind::Normal(normal) if normal.item.path == sym::doc => { + normal.item.value_str().map(|s| (s, CommentKind::Line)) + } _ => None, } } @@ -265,9 +290,7 @@ impl Attribute { pub fn doc_str(&self) -> Option { match &self.kind { AttrKind::DocComment(.., data) => Some(*data), - AttrKind::Normal(normal) if normal.item.path == sym::doc => { - normal.item.meta_kind().and_then(|kind| kind.value_str()) - } + AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(), _ => None, } } @@ -508,15 +531,12 @@ impl MetaItem { impl MetaItemKind { pub fn value_str(&self) -> Option { match self { - MetaItemKind::NameValue(v) => match v.kind { - LitKind::Str(s, _) => Some(s), - _ => None, - }, + MetaItemKind::NameValue(v) => v.kind.str(), _ => None, } } - fn list_from_tokens(tokens: TokenStream) -> Option { + fn list_from_tokens(tokens: TokenStream) -> Option> { let mut tokens = tokens.into_trees().peekable(); let mut result = Vec::new(); while tokens.peek().is_some() { @@ -527,7 +547,7 @@ impl MetaItemKind { _ => return None, } } - Some(MetaItemKind::List(result)) + Some(result) } fn name_value_from_tokens( @@ -551,7 +571,7 @@ impl MetaItemKind { dspan: _, delim: MacDelimiter::Parenthesis, tokens, - }) => MetaItemKind::list_from_tokens(tokens.clone()), + }) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List), AttrArgs::Delimited(..) => None, AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { ExprKind::Lit(token_lit) => { @@ -573,7 +593,7 @@ impl MetaItemKind { Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => { let inner_tokens = inner_tokens.clone(); tokens.next(); - MetaItemKind::list_from_tokens(inner_tokens) + MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List) } Some(TokenTree::Delimited(..)) => None, Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 9831e98fe371..3ebbb2cbdfb8 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -319,74 +319,62 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } } else if attr.has_name(sym::instruction_set) { - codegen_fn_attrs.instruction_set = match attr.meta_kind() { - Some(MetaItemKind::List(ref items)) => match items.as_slice() { - [NestedMetaItem::MetaItem(set)] => { - let segments = - set.path.segments.iter().map(|x| x.ident.name).collect::>(); - match segments.as_slice() { - [sym::arm, sym::a32] | [sym::arm, sym::t32] => { - if !tcx.sess.target.has_thumb_interworking { - struct_span_err!( - tcx.sess.diagnostic(), - attr.span, - E0779, - "target does not support `#[instruction_set]`" - ) - .emit(); - None - } else if segments[1] == sym::a32 { - Some(InstructionSetAttr::ArmA32) - } else if segments[1] == sym::t32 { - Some(InstructionSetAttr::ArmT32) - } else { - unreachable!() - } - } - _ => { + codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] { + [NestedMetaItem::MetaItem(set)] => { + let segments = + set.path.segments.iter().map(|x| x.ident.name).collect::>(); + match segments.as_slice() { + [sym::arm, sym::a32] | [sym::arm, sym::t32] => { + if !tcx.sess.target.has_thumb_interworking { struct_span_err!( tcx.sess.diagnostic(), attr.span, E0779, - "invalid instruction set specified", + "target does not support `#[instruction_set]`" ) .emit(); None + } else if segments[1] == sym::a32 { + Some(InstructionSetAttr::ArmA32) + } else if segments[1] == sym::t32 { + Some(InstructionSetAttr::ArmT32) + } else { + unreachable!() } } + _ => { + struct_span_err!( + tcx.sess.diagnostic(), + attr.span, + E0779, + "invalid instruction set specified", + ) + .emit(); + None + } } - [] => { - struct_span_err!( - tcx.sess.diagnostic(), - attr.span, - E0778, - "`#[instruction_set]` requires an argument" - ) - .emit(); - None - } - _ => { - struct_span_err!( - tcx.sess.diagnostic(), - attr.span, - E0779, - "cannot specify more than one instruction set" - ) - .emit(); - None - } - }, - _ => { + } + [] => { struct_span_err!( tcx.sess.diagnostic(), attr.span, E0778, - "must specify an instruction set" + "`#[instruction_set]` requires an argument" ) .emit(); None } - }; + _ => { + struct_span_err!( + tcx.sess.diagnostic(), + attr.span, + E0779, + "cannot specify more than one instruction set" + ) + .emit(); + None + } + }) } else if attr.has_name(sym::repr) { codegen_fn_attrs.alignment = match attr.meta_item_list() { Some(items) => match items.as_slice() { diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 4c6a9b23fdf1..f4da1aaec113 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -4,7 +4,7 @@ //! but are not declared in one single location (unlike lang features), which means we need to //! collect them instead. -use rustc_ast::{Attribute, MetaItemKind}; +use rustc_ast::Attribute; use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER}; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; @@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { // Find a stability attribute: one of #[stable(…)], #[unstable(…)], // #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable]. if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) { - let meta_kind = attr.meta_kind(); - if let Some(MetaItemKind::List(ref metas)) = meta_kind { + if let Some(metas) = attr.meta_item_list() { let mut feature = None; let mut since = None; for meta in metas { From e30cd18fcc8905d5c726b371cb6c1c4e081bc5f2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 2 Feb 2023 10:22:44 +1100 Subject: [PATCH 032/137] Reinstate the `hir-stats.rs` tests on stage 1. --- tests/ui/stats/hir-stats.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs index 0b89d0b160b3..9bb87026b641 100644 --- a/tests/ui/stats/hir-stats.rs +++ b/tests/ui/stats/hir-stats.rs @@ -1,7 +1,11 @@ // check-pass // compile-flags: -Zhir-stats // only-x86_64 -// ignore-stage1 FIXME: remove after next bootstrap bump + +// Type layouts sometimes change. When that happens, until the next bootstrap +// bump occurs, stage1 and stage2 will give different outputs for this test. +// Add an `ignore-stage1` comment marker to work around that problem during +// that time. // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. From cc8f990e917b8bc1a71fe5869c553821f6629673 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 31 Jan 2023 03:49:11 +0000 Subject: [PATCH 033/137] Add tests to assert current behavior of large future sizes Based on a couple of sources: - https://swatinem.de/blog/future-size/ - https://github.com/rust-lang/rust/issues/62958 --- tests/ui/future-sizes/future-as-arg.rs | 19 ++++++++ tests/ui/future-sizes/large-arg.rs | 17 ++++++++ tests/ui/future-sizes/large-arg.stdout | 60 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 tests/ui/future-sizes/future-as-arg.rs create mode 100644 tests/ui/future-sizes/large-arg.rs create mode 100644 tests/ui/future-sizes/large-arg.stdout diff --git a/tests/ui/future-sizes/future-as-arg.rs b/tests/ui/future-sizes/future-as-arg.rs new file mode 100644 index 000000000000..e021ff512e3c --- /dev/null +++ b/tests/ui/future-sizes/future-as-arg.rs @@ -0,0 +1,19 @@ +// edition: 2021 +// run-pass + +async fn test(_arg: [u8; 8192]) {} + +async fn use_future(fut: impl std::future::Future) { + fut.await +} + +fn main() { + let n = std::mem::size_of_val(&use_future(use_future(use_future(use_future(use_future( + use_future(use_future(use_future(use_future(use_future(test( + [0; 8192] + )))))) + )))))); + println!("size is: {n}"); + // Not putting an exact number in case it slightly changes over different commits + assert!(n > 8000000); +} diff --git a/tests/ui/future-sizes/large-arg.rs b/tests/ui/future-sizes/large-arg.rs new file mode 100644 index 000000000000..c543c71f13cd --- /dev/null +++ b/tests/ui/future-sizes/large-arg.rs @@ -0,0 +1,17 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// edition: 2021 +// build-pass + +pub async fn test() { + let _ = a([0u8; 1024]).await; +} + +pub async fn a(t: T) -> T { + b(t).await +} +async fn b(t: T) -> T { + c(t).await +} +async fn c(t: T) -> T { + t +} diff --git a/tests/ui/future-sizes/large-arg.stdout b/tests/ui/future-sizes/large-arg.stdout new file mode 100644 index 000000000000..cd5a22a270a5 --- /dev/null +++ b/tests/ui/future-sizes/large-arg.stdout @@ -0,0 +1,60 @@ +print-type-size type: `[async fn body@$DIR/large-arg.rs:5:21: 7:2]`: 3076 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 3075 bytes +print-type-size field `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:9:30: 11:2]`: 3075 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 3074 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size field `.__awaitee`: 2050 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:9:30: 11:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size field `.value`: 3075 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:9:30: 11:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 3075 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 3075 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:12:26: 14:2]`: 2050 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 2049 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size field `.__awaitee`: 1025 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:12:26: 14:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size field `.value`: 2050 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:12:26: 14:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 2050 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 2050 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:15:26: 17:2]`: 1025 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 1024 bytes +print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:15:26: 17:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:15:26: 17:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 1025 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 1025 bytes +print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Ready`: 1024 bytes +print-type-size field `.0`: 1024 bytes +print-type-size variant `Pending`: 0 bytes From 7e56265ea04a4082283f6855903d2caf9eb2b7a7 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:04:18 +0000 Subject: [PATCH 034/137] Update based on PR comments --- tests/ui/{ => async-await}/future-sizes/future-as-arg.rs | 7 ++++--- tests/ui/{ => async-await}/future-sizes/large-arg.rs | 0 tests/ui/{ => async-await}/future-sizes/large-arg.stdout | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename tests/ui/{ => async-await}/future-sizes/future-as-arg.rs (64%) rename tests/ui/{ => async-await}/future-sizes/large-arg.rs (100%) rename tests/ui/{ => async-await}/future-sizes/large-arg.stdout (100%) diff --git a/tests/ui/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs similarity index 64% rename from tests/ui/future-sizes/future-as-arg.rs rename to tests/ui/async-await/future-sizes/future-as-arg.rs index e021ff512e3c..8ebb527bd105 100644 --- a/tests/ui/future-sizes/future-as-arg.rs +++ b/tests/ui/async-await/future-sizes/future-as-arg.rs @@ -1,5 +1,6 @@ // edition: 2021 // run-pass +// ignore-pass async fn test(_arg: [u8; 8192]) {} @@ -8,12 +9,12 @@ async fn use_future(fut: impl std::future::Future) { } fn main() { - let n = std::mem::size_of_val(&use_future(use_future(use_future(use_future(use_future( + let actual = std::mem::size_of_val(&use_future(use_future(use_future(use_future(use_future( use_future(use_future(use_future(use_future(use_future(test( [0; 8192] )))))) )))))); - println!("size is: {n}"); // Not putting an exact number in case it slightly changes over different commits - assert!(n > 8000000); + let expected = 8000000; + assert!(actual > expected, "expected: >{expected}, actual: {actual}"); } diff --git a/tests/ui/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs similarity index 100% rename from tests/ui/future-sizes/large-arg.rs rename to tests/ui/async-await/future-sizes/large-arg.rs diff --git a/tests/ui/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout similarity index 100% rename from tests/ui/future-sizes/large-arg.stdout rename to tests/ui/async-await/future-sizes/large-arg.stdout From cb6de47d3b35bdb5d0c9614eb27d07186136ce2f Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Tue, 31 Jan 2023 18:56:55 +0000 Subject: [PATCH 035/137] Move ignore-pass to large-arg test --- .../async-await/future-sizes/future-as-arg.rs | 1 - .../ui/async-await/future-sizes/large-arg.rs | 1 + .../async-await/future-sizes/large-arg.stdout | 20 +++++++++---------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs index 8ebb527bd105..6a545c6a8aa6 100644 --- a/tests/ui/async-await/future-sizes/future-as-arg.rs +++ b/tests/ui/async-await/future-sizes/future-as-arg.rs @@ -1,6 +1,5 @@ // edition: 2021 // run-pass -// ignore-pass async fn test(_arg: [u8; 8192]) {} diff --git a/tests/ui/async-await/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs index c543c71f13cd..7e7ff9d8d00e 100644 --- a/tests/ui/async-await/future-sizes/large-arg.rs +++ b/tests/ui/async-await/future-sizes/large-arg.rs @@ -1,6 +1,7 @@ // compile-flags: -Z print-type-sizes --crate-type=lib // edition: 2021 // build-pass +// ignore-pass pub async fn test() { let _ = a([0u8; 1024]).await; diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index cd5a22a270a5..ccc91a1d19be 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -1,11 +1,11 @@ -print-type-size type: `[async fn body@$DIR/large-arg.rs:5:21: 7:2]`: 3076 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 3075 bytes print-type-size field `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:9:30: 11:2]`: 3075 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 3074 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes @@ -16,13 +16,13 @@ print-type-size variant `Returned`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:9:30: 11:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:9:30: 11:2]>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3075 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:12:26: 14:2]`: 2050 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 2049 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes @@ -33,13 +33,13 @@ print-type-size variant `Returned`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:12:26: 14:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:12:26: 14:2]>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 2050 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `[async fn body@$DIR/large-arg.rs:15:26: 17:2]`: 1025 bytes, alignment: 1 bytes +print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes @@ -47,9 +47,9 @@ print-type-size variant `Returned`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:15:26: 17:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:15:26: 17:2]>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1025 bytes From 776918971d3320d6858da12112343753b1dd875e Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Wed, 1 Feb 2023 21:09:24 +0000 Subject: [PATCH 036/137] Update test to not trigger stack overflow --- tests/ui/async-await/future-sizes/future-as-arg.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs index 6a545c6a8aa6..93c69b05254d 100644 --- a/tests/ui/async-await/future-sizes/future-as-arg.rs +++ b/tests/ui/async-await/future-sizes/future-as-arg.rs @@ -1,19 +1,16 @@ // edition: 2021 // run-pass -async fn test(_arg: [u8; 8192]) {} +async fn test(_arg: [u8; 16]) {} async fn use_future(fut: impl std::future::Future) { fut.await } fn main() { - let actual = std::mem::size_of_val(&use_future(use_future(use_future(use_future(use_future( - use_future(use_future(use_future(use_future(use_future(test( - [0; 8192] - )))))) - )))))); - // Not putting an exact number in case it slightly changes over different commits - let expected = 8000000; + let actual = std::mem::size_of_val( + &use_future(use_future(use_future(use_future(use_future(test([0; 16]))))))); + // Not using an exact number in case it slightly changes over different commits + let expected = 550; assert!(actual > expected, "expected: >{expected}, actual: {actual}"); } From 1a65219a49cb9797f228b04929ac02236d690435 Mon Sep 17 00:00:00 2001 From: Bryan Garza <1396101+bryangarza@users.noreply.github.com> Date: Thu, 2 Feb 2023 01:38:14 +0000 Subject: [PATCH 037/137] Bless tests after rebase --- .../async-await/future-sizes/large-arg.stdout | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index ccc91a1d19be..c206d7931707 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -1,21 +1,21 @@ print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 3075 bytes -print-type-size field `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 3074 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size field `.__awaitee`: 2050 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size local `.__awaitee`: 2050 bytes print-type-size variant `Unresumed`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes @@ -25,14 +25,14 @@ print-type-size field `.value`: 3075 bytes print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Suspend0`: 2049 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size field `.__awaitee`: 1025 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size local `.__awaitee`: 1025 bytes print-type-size variant `Unresumed`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes @@ -42,11 +42,11 @@ print-type-size field `.value`: 2050 bytes print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes -print-type-size field `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes From 64f5293956de9dc4e336906f1c7fef8415c292de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Feb 2023 05:49:07 +0000 Subject: [PATCH 038/137] Don't cause a cycle when formatting query description that references a FnDef --- compiler/rustc_middle/src/ty/print/pretty.rs | 23 +++++++++++++++---- compiler/rustc_query_impl/src/plumbing.rs | 13 +++++++---- tests/ui/async-await/no-const-async.stderr | 4 ++-- tests/ui/impl-trait/auto-trait-leak.stderr | 4 ++-- .../ui/parser/fn-header-semantic-fail.stderr | 12 +++++----- ...no-query-in-printing-during-query-descr.rs | 6 +++++ ...uery-in-printing-during-query-descr.stderr | 9 ++++++++ 7 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 tests/ui/query-system/no-query-in-printing-during-query-descr.rs create mode 100644 tests/ui/query-system/no-query-in-printing-during-query-descr.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6a20f62b6f9b..cb47522877c2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -675,8 +675,12 @@ pub trait PrettyPrinter<'tcx>: p!(")") } ty::FnDef(def_id, substs) => { - let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); - p!(print(sig), " {{", print_value_path(def_id, substs), "}}"); + if NO_QUERIES.with(|q| q.get()) { + p!(print_def_path(def_id, substs)); + } else { + let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); + p!(print(sig), " {{", print_value_path(def_id, substs), "}}"); + } } ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), ty::Infer(infer_ty) => { @@ -732,13 +736,13 @@ pub trait PrettyPrinter<'tcx>: } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { - // FIXME(eddyb) print this with `print_def_path`. // We use verbose printing in 'NO_QUERIES' mode, to // avoid needing to call `predicates_of`. This should // only affect certain debug messages (e.g. messages printed // from `rustc_middle::ty` during the computation of `tcx.predicates_of`), // and should have no effect on any compiler output. - if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) { + if self.should_print_verbose() { + // FIXME(eddyb) print this with `print_def_path`. p!(write("Opaque({:?}, {:?})", def_id, substs)); return Ok(self); } @@ -746,6 +750,8 @@ pub trait PrettyPrinter<'tcx>: let parent = self.tcx().parent(def_id); match self.tcx().def_kind(parent) { DefKind::TyAlias | DefKind::AssocTy => { + // NOTE: I know we should check for NO_QUERIES here, but it's alright. + // `type_of` on a TAIT should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = *self.tcx().type_of(parent).kind() { @@ -760,7 +766,14 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(def_id, substs)); return Ok(self); } - _ => return self.pretty_print_opaque_impl_type(def_id, substs), + _ => { + if NO_QUERIES.with(|q| q.get()) { + p!(print_def_path(def_id, &[])); + return Ok(self); + } else { + return self.pretty_print_opaque_impl_type(def_id, substs); + } + } } } ty::Str => p!("str"), diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6125ad4eff11..4dea03c1ef6a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -314,11 +314,14 @@ pub(crate) fn create_query_frame< kind: DepKind, name: &'static str, ) -> QueryStackFrame { - // Disable visible paths printing for performance reasons. - // Showing visible path instead of any path is not that important in production. - let description = ty::print::with_no_visible_paths!( - // Force filename-line mode to avoid invoking `type_of` query. - ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key)) + // Avoid calling queries while formatting the description + let description = ty::print::with_no_queries!( + // Disable visible paths printing for performance reasons. + // Showing visible path instead of any path is not that important in production. + ty::print::with_no_visible_paths!( + // Force filename-line mode to avoid invoking `type_of` query. + ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key)) + ) ); let description = if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description }; diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr index c5bd520aaea0..71c228958f6f 100644 --- a/tests/ui/async-await/no-const-async.stderr +++ b/tests/ui/async-await/no-const-async.stderr @@ -28,8 +28,8 @@ note: ...which requires const checking `x`... | LL | pub const async fn x() {} | ^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing whether `impl core::future::future::Future` is freeze... - = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which requires computing whether `x::{opaque#0}` is freeze... + = note: ...which requires evaluating trait selection obligation `x::{opaque#0}: core::marker::Freeze`... = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/no-const-async.rs:4:1 diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index feedfc40aaf4..fd0358421ebf 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -39,7 +39,7 @@ note: ...which requires type-checking `cycle1`... | LL | send(cycle2().clone()); | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... + = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... --> $DIR/auto-trait-leak.rs:19:16 | @@ -80,7 +80,7 @@ note: ...which requires type-checking `cycle2`... | LL | send(cycle1().clone()); | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... + = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: core::marker::Send`... = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/auto-trait-leak.rs:1:1 diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index 038fdfb2d51b..2d8bd19a7310 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -209,8 +209,8 @@ note: ...which requires const checking `main::ff5`... | LL | const async unsafe extern "C" fn ff5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing whether `impl core::future::future::Future` is freeze... - = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which requires computing whether `main::ff5::{opaque#0}` is freeze... + = note: ...which requires evaluating trait selection obligation `main::ff5::{opaque#0}: core::marker::Freeze`... = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 @@ -245,8 +245,8 @@ note: ...which requires const checking `main::` is freeze... - = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which requires computing whether `main::::ft5::{opaque#0}` is freeze... + = note: ...which requires evaluating trait selection obligation `main::::ft5::{opaque#0}: core::marker::Freeze`... = note: ...which again requires computing type of `main::::ft5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 @@ -281,8 +281,8 @@ note: ...which requires const checking `main::` is freeze... - = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which requires computing whether `main::::fi5::{opaque#0}` is freeze... + = note: ...which requires evaluating trait selection obligation `main::::fi5::{opaque#0}: core::marker::Freeze`... = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/fn-header-semantic-fail.rs:5:1 diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.rs b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs new file mode 100644 index 000000000000..45b7043e2f6f --- /dev/null +++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs @@ -0,0 +1,6 @@ +fn a() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &a +} + +fn main() {} diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr new file mode 100644 index 000000000000..35e608b6b232 --- /dev/null +++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr @@ -0,0 +1,9 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/no-query-in-printing-during-query-descr.rs:1:11 + | +LL | fn a() -> _ { + | ^ not allowed in type signatures + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. From e4b2936983046f4128fcd3a390b401ae0cbaaacc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Jan 2023 18:08:50 +0000 Subject: [PATCH 039/137] Revert "Teach parser to understand fake anonymous enum syntax" and related commits Revert "review comment: Remove AST AnonTy" This reverts commit 020cca8d36cb678e3ddc2ead41364be314d19e93. Revert "Ensure macros are not affected" This reverts commit 12d18e403139eeeeb339e8611b2bed4910864edb. Revert "Emit fewer errors on patterns with possible type ascription" This reverts commit c847a01a3b1f620c4fdb98c75805033e768975d1. Revert "Teach parser to understand fake anonymous enum syntax" This reverts commit 2d824206655bfb26cb5eed43490ee396542b153e. --- compiler/rustc_ast/src/visit.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 52 +++--------- compiler/rustc_parse/src/parser/pat.rs | 3 +- compiler/rustc_parse/src/parser/ty.rs | 65 +-------------- tests/ui/parser/anon-enums.rs | 17 ---- tests/ui/parser/anon-enums.stderr | 68 --------------- tests/ui/parser/fake-anon-enums-in-macros.rs | 20 ----- .../issues/issue-87086-colon-path-sep.rs | 1 + .../issues/issue-87086-colon-path-sep.stderr | 83 ++++++------------- 9 files changed, 47 insertions(+), 266 deletions(-) delete mode 100644 tests/ui/parser/anon-enums.rs delete mode 100644 tests/ui/parser/anon-enums.stderr delete mode 100644 tests/ui/parser/fake-anon-enums-in-macros.rs diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e7b2e4b1cb4b..bdb1879ec201 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -403,8 +403,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); visitor.visit_ty(&mutable_type.ty) } - TyKind::Tup(tys) => { - walk_list!(visitor, visit_ty, tys); + TyKind::Tup(tuple_element_types) => { + walk_list!(visitor, visit_ty, tuple_element_types); } TyKind::BareFn(function_declaration) => { walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 26274822ed8a..16d5edfd303a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2394,7 +2394,7 @@ impl<'a> Parser<'a> { /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - pub(crate) fn maybe_recover_colon_colon_in_pat_typo_or_anon_enum( + pub(crate) fn maybe_recover_colon_colon_in_pat_typo( &mut self, mut first_pat: P, expected: Option, @@ -2405,41 +2405,26 @@ impl<'a> Parser<'a> { if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) { - let mut snapshot_type = self.create_snapshot_for_diagnostic(); - snapshot_type.bump(); // `:` - match snapshot_type.parse_ty() { - Err(inner_err) => { - inner_err.cancel(); - } - Ok(ty) => { - let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else { - return first_pat; - }; - err.span_label(ty.span, "specifying the type of a pattern isn't supported"); - self.restore_snapshot(snapshot_type); - let span = first_pat.span.to(ty.span); - first_pat = self.mk_pat(span, PatKind::Wild); - err.emit(); - } - } return first_pat; } // The pattern looks like it might be a path with a `::` -> `:` typo: // `match foo { bar:baz => {} }` - let colon_span = self.token.span; + let span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let mut snapshot_pat = self.create_snapshot_for_diagnostic(); - let mut snapshot_type = self.create_snapshot_for_diagnostic(); + let snapshot = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - snapshot_pat.bump(); // Skip the `:`. - snapshot_type.bump(); // Skip the `:`. - match snapshot_pat.parse_pat_no_top_alt(expected) { + self.bump(); // Skip the `:`. + match self.parse_pat_no_top_alt(expected) { Err(inner_err) => { + // Carry on as if we had not done anything, callers will emit a + // reasonable error. inner_err.cancel(); + err.cancel(); + self.restore_snapshot(snapshot); } Ok(mut pat) => { // We've parsed the rest of the pattern. @@ -2503,8 +2488,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion_verbose( - colon_span.until(self.look_ahead(1, |t| t.span)), + err.span_suggestion( + span, "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2512,24 +2497,13 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - self.restore_snapshot(snapshot_pat); + err.emit(); } } - match snapshot_type.parse_ty() { - Err(inner_err) => { - inner_err.cancel(); - } - Ok(ty) => { - err.span_label(ty.span, "specifying the type of a pattern isn't supported"); - self.restore_snapshot(snapshot_type); - let new_span = first_pat.span.to(ty.span); - first_pat = self.mk_pat(new_span, PatKind::Wild); - } - } - err.emit(); } _ => { // Carry on as if we had not done anything. This should be unreachable. + self.restore_snapshot(snapshot); } }; first_pat diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 88c75fd81e75..e75554ba124b 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -148,8 +148,7 @@ impl<'a> Parser<'a> { // Check if the user wrote `foo:bar` instead of `foo::bar`. if ra == RecoverColon::Yes { - first_pat = - self.maybe_recover_colon_colon_in_pat_typo_or_anon_enum(first_pat, expected); + first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected); } if let Some(leading_vert_span) = leading_vert_span { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306cbcff149f..646e2f45e640 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -17,7 +17,6 @@ use rustc_ast::{ self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, }; -use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident}; @@ -50,24 +49,17 @@ pub(super) enum AllowPlus { No, } -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq)] pub(super) enum RecoverQPath { Yes, No, } -#[derive(PartialEq, Clone, Copy)] pub(super) enum RecoverQuestionMark { Yes, No, } -#[derive(PartialEq, Clone, Copy)] -pub(super) enum RecoverAnonEnum { - Yes, - No, -} - /// Signals whether parsing a type should recover `->`. /// /// More specifically, when parsing a function like: @@ -100,7 +92,7 @@ impl RecoverReturnSign { } // Is `...` (`CVarArgs`) legal at this level of type parsing? -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq)] enum AllowCVariadic { Yes, No, @@ -125,7 +117,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -140,7 +131,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, Some(ty_params), RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -155,7 +145,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, ) } @@ -173,7 +162,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -187,7 +175,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - RecoverAnonEnum::No, ) } @@ -199,7 +186,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - RecoverAnonEnum::No, ) } @@ -212,7 +198,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::OnlyFatArrow, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::No, ) } @@ -232,7 +217,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -247,7 +231,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - RecoverAnonEnum::Yes, )?; FnRetTy::Ty(ty) } else { @@ -263,7 +246,6 @@ impl<'a> Parser<'a> { recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, - recover_anon_enum: RecoverAnonEnum, ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -347,50 +329,9 @@ impl<'a> Parser<'a> { AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?, AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty), } - if RecoverQuestionMark::Yes == recover_question_mark { + if let RecoverQuestionMark::Yes = recover_question_mark { ty = self.maybe_recover_from_question_mark(ty); } - if recover_anon_enum == RecoverAnonEnum::Yes - && self.check_noexpect(&token::BinOp(token::Or)) - && self.look_ahead(1, |t| t.can_begin_type()) - { - let mut pipes = vec![self.token.span]; - let mut types = vec![ty]; - loop { - if !self.eat(&token::BinOp(token::Or)) { - break; - } - pipes.push(self.prev_token.span); - types.push(self.parse_ty_common( - allow_plus, - allow_c_variadic, - recover_qpath, - recover_return_sign, - ty_generics, - recover_question_mark, - RecoverAnonEnum::No, - )?); - } - let mut err = self.struct_span_err(pipes, "anonymous enums are not supported"); - for ty in &types { - err.span_label(ty.span, ""); - } - err.help(&format!( - "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}", - types - .iter() - .enumerate() - .map(|(i, t)| format!( - " Variant{}({}),", - i + 1, // Lets not confuse people with zero-indexing :) - pprust::to_string(|s| s.print_type(&t)), - )) - .collect::>() - .join("\n"), - )); - err.emit(); - return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err)); - } if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } diff --git a/tests/ui/parser/anon-enums.rs b/tests/ui/parser/anon-enums.rs deleted file mode 100644 index 56b8a3d43bed..000000000000 --- a/tests/ui/parser/anon-enums.rs +++ /dev/null @@ -1,17 +0,0 @@ -fn foo(x: bool | i32) -> i32 | f64 { -//~^ ERROR anonymous enums are not supported -//~| ERROR anonymous enums are not supported - match x { - x: i32 => x, //~ ERROR expected - true => 42., - false => 0.333, - } -} - -fn main() { - match foo(true) { - 42: i32 => (), //~ ERROR expected - _: f64 => (), //~ ERROR expected - x: i32 => (), //~ ERROR expected - } -} diff --git a/tests/ui/parser/anon-enums.stderr b/tests/ui/parser/anon-enums.stderr deleted file mode 100644 index 841582256609..000000000000 --- a/tests/ui/parser/anon-enums.stderr +++ /dev/null @@ -1,68 +0,0 @@ -error: anonymous enums are not supported - --> $DIR/anon-enums.rs:1:16 - | -LL | fn foo(x: bool | i32) -> i32 | f64 { - | ---- ^ --- - | - = help: create a named `enum` and use it here instead: - enum Name { - Variant1(bool), - Variant2(i32), - } - -error: anonymous enums are not supported - --> $DIR/anon-enums.rs:1:30 - | -LL | fn foo(x: bool | i32) -> i32 | f64 { - | --- ^ --- - | - = help: create a named `enum` and use it here instead: - enum Name { - Variant1(i32), - Variant2(f64), - } - -error: expected one of `@` or `|`, found `:` - --> $DIR/anon-enums.rs:5:10 - | -LL | x: i32 => x, - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | x::i32 => x, - | ~~ - -error: expected one of `...`, `..=`, `..`, or `|`, found `:` - --> $DIR/anon-enums.rs:13:11 - | -LL | 42: i32 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `...`, `..=`, `..`, or `|` - -error: expected `|`, found `:` - --> $DIR/anon-enums.rs:14:10 - | -LL | _: f64 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected `|` - -error: expected one of `@` or `|`, found `:` - --> $DIR/anon-enums.rs:15:10 - | -LL | x: i32 => (), - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | x::i32 => (), - | ~~ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/parser/fake-anon-enums-in-macros.rs b/tests/ui/parser/fake-anon-enums-in-macros.rs deleted file mode 100644 index 38fe8dee2382..000000000000 --- a/tests/ui/parser/fake-anon-enums-in-macros.rs +++ /dev/null @@ -1,20 +0,0 @@ -// build-pass -macro_rules! check_ty { - ($Z:ty) => { compile_error!("triggered"); }; - ($X:ty | $Y:ty) => { $X }; -} - -macro_rules! check { - ($Z:ty) => { compile_error!("triggered"); }; - ($X:ty | $Y:ty) => { }; -} - -check! { i32 | u8 } - -fn foo(x: check_ty! { i32 | u8 }) -> check_ty! { i32 | u8 } { - x -} -fn main() { - let x: check_ty! { i32 | u8 } = 42; - let _: check_ty! { i32 | u8 } = foo(x); -} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index e1ea38f2795d..0b7b67496d6f 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -68,6 +68,7 @@ fn main() { Foo:Bar::Baz => {} //~^ ERROR: expected one of //~| HELP: maybe write a path separator here + //~| ERROR: failed to resolve: `Bar` is a variant, not a module } match myfoo { Foo::Bar => {} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 63b072ac4cdc..2050a16beb34 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -2,118 +2,89 @@ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:17:12 | LL | Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | Foo::Bar => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:23:17 | LL | qux::Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of 8 possible tokens - | -help: maybe write a path separator here - | -LL | qux::Foo::Bar => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:29:12 | LL | qux:Foo::Baz => {} - | ^-------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:35:12 | LL | qux: Foo::Baz if true => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | qux::Foo::Baz if true => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:40:15 | LL | if let Foo:Bar = f() { - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | if let Foo::Bar = f() { - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:48:16 | LL | ref qux: Foo::Baz => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | ref qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:57:16 | LL | mut qux: Foo::Baz => {} - | ^ -------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | mut qux::Foo::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:68:12 | LL | Foo:Bar::Baz => {} - | ^-------- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | Foo::Bar::Baz => {} - | ~~ + | help: maybe write a path separator here: `::` error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:74:12 + --> $DIR/issue-87086-colon-path-sep.rs:75:12 | LL | Foo:Bar => {} - | ^--- specifying the type of a pattern isn't supported + | ^ | | | expected one of `@` or `|` - | -help: maybe write a path separator here - | -LL | Foo::Bar => {} - | ~~ + | help: maybe write a path separator here: `::` -error: aborting due to 9 previous errors +error[E0433]: failed to resolve: `Bar` is a variant, not a module + --> $DIR/issue-87086-colon-path-sep.rs:68:13 + | +LL | Foo:Bar::Baz => {} + | ^^^ `Bar` is a variant, not a module +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0433`. From 39db65c526ae3b97f0ee90642242c8c07865707e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Jan 2023 18:39:33 +0000 Subject: [PATCH 040/137] Add a test --- tests/ui/parser/anon-enums-are-ambiguous.rs | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/ui/parser/anon-enums-are-ambiguous.rs diff --git a/tests/ui/parser/anon-enums-are-ambiguous.rs b/tests/ui/parser/anon-enums-are-ambiguous.rs new file mode 100644 index 000000000000..b0173cf98e0a --- /dev/null +++ b/tests/ui/parser/anon-enums-are-ambiguous.rs @@ -0,0 +1,26 @@ +// check-pass + +macro_rules! test_expr { + ($expr:expr) => {}; +} + +macro_rules! test_ty { + ($a:ty | $b:ty) => {}; +} + +fn main() { + test_expr!(a as fn() -> B | C); + // Do not break the `|` operator. + + test_expr!(|_: fn() -> B| C | D); + // Do not break `-> Ret` in closure args. + + test_ty!(A | B); + // We can't support anon enums in arbitrary positions. + + test_ty!(fn() -> A | B); + // Don't break fn ptrs. + + test_ty!(impl Fn() -> A | B); + // Don't break parenthesized generics. +} From 9dd5d3e8e421193be34fa822ab485de115174421 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 15 Jan 2023 21:31:04 +0000 Subject: [PATCH 041/137] Recover _ as .. in field pattern --- .../locales/en-US/parse.ftl | 4 +-- compiler/rustc_parse/src/errors.rs | 5 +++- compiler/rustc_parse/src/parser/pat.rs | 18 ++++++++----- ...ssue-46718-struct-pattern-dotdotdot.stderr | 7 ++++- tests/ui/parser/issue-102806.stderr | 7 ++++- tests/ui/parser/issues/issue-63135.stderr | 7 ++++- ...uct-enum-ignoring-field-with-underscore.rs | 3 +-- ...enum-ignoring-field-with-underscore.stderr | 27 ++++++------------- 8 files changed, 44 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 21cf4bd789c7..6752f05b044e 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -535,8 +535,8 @@ parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` ar parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern -parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...` - .suggestion = to omit remaining fields, use one fewer `.` +parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}` + .suggestion = to omit remaining fields, use `..` parse_expected_comma_after_pattern_field = expected `,` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 145611923ff1..20da8ce5b6e7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; @@ -1802,8 +1804,9 @@ pub(crate) struct EnumPatternInsteadOfIdentifier { #[diag(parse_dot_dot_dot_for_remaining_fields)] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] - #[suggestion(code = "..", applicability = "machine-applicable")] + #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")] pub span: Span, + pub token_str: Cow<'static, str>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 88c75fd81e75..c982d7f99a91 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -963,12 +963,15 @@ impl<'a> Parser<'a> { } ate_comma = false; - if self.check(&token::DotDot) || self.token == token::DotDotDot { + if self.check(&token::DotDot) + || self.check_noexpect(&token::DotDotDot) + || self.check_keyword(kw::Underscore) + { etc = true; let mut etc_sp = self.token.span; - self.recover_one_fewer_dotdot(); - self.bump(); // `..` || `...` + self.recover_bad_dot_dot(); + self.bump(); // `..` || `...` || `_` if self.token == token::CloseDelim(Delimiter::Brace) { etc_span = Some(etc_sp); @@ -1061,14 +1064,15 @@ impl<'a> Parser<'a> { Ok((fields, etc)) } - /// Recover on `...` as if it were `..` to avoid further errors. + /// Recover on `...` or `_` as if it were `..` to avoid further errors. /// See issue #46718. - fn recover_one_fewer_dotdot(&self) { - if self.token != token::DotDotDot { + fn recover_bad_dot_dot(&self) { + if self.token == token::DotDot { return; } - self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span }); + let token_str = pprust::token_to_string(&self.token); + self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str }); } fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> { diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr index bfe1ed32859b..589b2c378492 100644 --- a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr +++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr @@ -2,7 +2,12 @@ error: expected field pattern, found `...` --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55 | LL | PersonalityInventory { expressivity: exp, ... } => exp - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | PersonalityInventory { expressivity: exp, .. } => exp + | ~~ error: aborting due to previous error diff --git a/tests/ui/parser/issue-102806.stderr b/tests/ui/parser/issue-102806.stderr index 6872b8bc0afe..ba8174a823b2 100644 --- a/tests/ui/parser/issue-102806.stderr +++ b/tests/ui/parser/issue-102806.stderr @@ -32,7 +32,12 @@ error: expected field pattern, found `...` --> $DIR/issue-102806.rs:21:22 | LL | let V3 { z: val, ... } = v; - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | let V3 { z: val, .. } = v; + | ~~ error[E0063]: missing fields `x` and `y` in initializer of `V3` --> $DIR/issue-102806.rs:17:13 diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr index 80e9ac5bedf1..e0dc356d5467 100644 --- a/tests/ui/parser/issues/issue-63135.stderr +++ b/tests/ui/parser/issues/issue-63135.stderr @@ -20,7 +20,12 @@ error: expected field pattern, found `...` --> $DIR/issue-63135.rs:3:8 | LL | fn i(n{...,f # - | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + | ^^^ + | +help: to omit remaining fields, use `..` + | +LL | fn i(n{..,f # + | ~~ error: expected `}`, found `,` --> $DIR/issue-63135.rs:3:11 diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs index c30b8a1e1f1a..b569993c6143 100644 --- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs @@ -7,6 +7,5 @@ fn main() { let foo = Some(Foo::Other); if let Some(Foo::Bar {_}) = foo {} - //~^ ERROR expected identifier, found reserved identifier `_` - //~| ERROR pattern does not mention field `bar` [E0027] + //~^ ERROR expected field pattern, found `_` } diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr index 16f751444a55..2f3a150e5cba 100644 --- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr @@ -1,24 +1,13 @@ -error: expected identifier, found reserved identifier `_` +error: expected field pattern, found `_` --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27 | LL | if let Some(Foo::Bar {_}) = foo {} - | ^ expected identifier, found reserved identifier + | ^ + | +help: to omit remaining fields, use `..` + | +LL | if let Some(Foo::Bar {..}) = foo {} + | ~~ -error[E0027]: pattern does not mention field `bar` - --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17 - | -LL | if let Some(Foo::Bar {_}) = foo {} - | ^^^^^^^^^^^^ missing field `bar` - | -help: include the missing field in the pattern - | -LL | if let Some(Foo::Bar {_, bar }) = foo {} - | ~~~~~~~ -help: if you don't care about this missing field, you can explicitly ignore it - | -LL | if let Some(Foo::Bar {_, .. }) = foo {} - | ~~~~~~ +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0027`. From 73681323e611972caa9a6107312c9e1f74467545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Feb 2023 07:12:10 +0100 Subject: [PATCH 042/137] Rename rustc_driver to rustc_driver_impl --- compiler/{rustc_driver => rustc_driver_impl}/Cargo.toml | 0 compiler/{rustc_driver => rustc_driver_impl}/README.md | 0 compiler/{rustc_driver => rustc_driver_impl}/src/args.rs | 0 compiler/{rustc_driver => rustc_driver_impl}/src/lib.rs | 0 compiler/{rustc_driver => rustc_driver_impl}/src/pretty.rs | 0 .../src/session_diagnostics.rs | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename compiler/{rustc_driver => rustc_driver_impl}/Cargo.toml (100%) rename compiler/{rustc_driver => rustc_driver_impl}/README.md (100%) rename compiler/{rustc_driver => rustc_driver_impl}/src/args.rs (100%) rename compiler/{rustc_driver => rustc_driver_impl}/src/lib.rs (100%) rename compiler/{rustc_driver => rustc_driver_impl}/src/pretty.rs (100%) rename compiler/{rustc_driver => rustc_driver_impl}/src/session_diagnostics.rs (100%) diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml similarity index 100% rename from compiler/rustc_driver/Cargo.toml rename to compiler/rustc_driver_impl/Cargo.toml diff --git a/compiler/rustc_driver/README.md b/compiler/rustc_driver_impl/README.md similarity index 100% rename from compiler/rustc_driver/README.md rename to compiler/rustc_driver_impl/README.md diff --git a/compiler/rustc_driver/src/args.rs b/compiler/rustc_driver_impl/src/args.rs similarity index 100% rename from compiler/rustc_driver/src/args.rs rename to compiler/rustc_driver_impl/src/args.rs diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs similarity index 100% rename from compiler/rustc_driver/src/lib.rs rename to compiler/rustc_driver_impl/src/lib.rs diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs similarity index 100% rename from compiler/rustc_driver/src/pretty.rs rename to compiler/rustc_driver_impl/src/pretty.rs diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs similarity index 100% rename from compiler/rustc_driver/src/session_diagnostics.rs rename to compiler/rustc_driver_impl/src/session_diagnostics.rs From 2aceaf4849a806813c31e9987df458e08c11e5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Feb 2023 07:17:46 +0100 Subject: [PATCH 043/137] Add a new `rustc_driver` dylib to rexport `rustc_driver_impl` --- Cargo.lock | 8 +++++++ compiler/rustc/Cargo.toml | 7 +++--- compiler/rustc_driver/Cargo.toml | 10 ++++++++ compiler/rustc_driver/src/lib.rs | 7 ++++++ compiler/rustc_driver_impl/Cargo.toml | 3 +-- .../src/session_diagnostics.rs | 24 +++++++++---------- .../locales/en-US/driver.ftl | 24 +++++++++---------- 7 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 compiler/rustc_driver/Cargo.toml create mode 100644 compiler/rustc_driver/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 14758d0f07ef..705210e44b24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3567,6 +3567,7 @@ dependencies = [ "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", + "rustc_driver_impl", "rustc_smir", ] @@ -3946,6 +3947,13 @@ dependencies = [ [[package]] name = "rustc_driver" version = "0.0.0" +dependencies = [ + "rustc_driver_impl", +] + +[[package]] +name = "rustc_driver_impl" +version = "0.0.0" dependencies = [ "libc", "rustc_ast", diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 27ee3dd2aeaf..41003ad83f31 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] rustc_driver = { path = "../rustc_driver" } +rustc_driver_impl = { path = "../rustc_driver_impl" } # Make sure rustc_codegen_ssa ends up in the sysroot, because this # crate is intended to be used by codegen backends, which may not be in-tree. @@ -20,6 +21,6 @@ features = ['unprefixed_malloc_on_supported_platforms'] [features] jemalloc = ['jemalloc-sys'] -llvm = ['rustc_driver/llvm'] -max_level_info = ['rustc_driver/max_level_info'] -rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler'] +llvm = ['rustc_driver_impl/llvm'] +max_level_info = ['rustc_driver_impl/max_level_info'] +rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler'] diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml new file mode 100644 index 000000000000..d7c295418ba6 --- /dev/null +++ b/compiler/rustc_driver/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rustc_driver" +version = "0.0.0" +edition = "2021" + +[lib] +crate-type = ["dylib"] + +[dependencies] +rustc_driver_impl = { path = "../rustc_driver_impl" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs new file mode 100644 index 000000000000..195fc71b649d --- /dev/null +++ b/compiler/rustc_driver/src/lib.rs @@ -0,0 +1,7 @@ +// This crate is intentionally empty and a rexport of `rustc_driver_impl` to allow the code in +// `rustc_driver_impl` to be compiled in parallel with other crates. + +#![allow(unused_extern_crates)] +extern crate rustc_driver_impl; + +pub use rustc_driver_impl::*; diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 59e937777483..af85b12c52b2 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -1,10 +1,9 @@ [package] -name = "rustc_driver" +name = "rustc_driver_impl" version = "0.0.0" edition = "2021" [lib] -crate-type = ["dylib"] [dependencies] tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index a7aef9cbc2c8..638b368f7021 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -1,67 +1,67 @@ use rustc_macros::Diagnostic; #[derive(Diagnostic)] -#[diag(driver_rlink_unable_to_read)] +#[diag(driver_impl_rlink_unable_to_read)] pub(crate) struct RlinkUnableToRead { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_rlink_wrong_file_type)] +#[diag(driver_impl_rlink_wrong_file_type)] pub(crate) struct RLinkWrongFileType; #[derive(Diagnostic)] -#[diag(driver_rlink_empty_version_number)] +#[diag(driver_impl_rlink_empty_version_number)] pub(crate) struct RLinkEmptyVersionNumber; #[derive(Diagnostic)] -#[diag(driver_rlink_encoding_version_mismatch)] +#[diag(driver_impl_rlink_encoding_version_mismatch)] pub(crate) struct RLinkEncodingVersionMismatch { pub version_array: String, pub rlink_version: u32, } #[derive(Diagnostic)] -#[diag(driver_rlink_rustc_version_mismatch)] +#[diag(driver_impl_rlink_rustc_version_mismatch)] pub(crate) struct RLinkRustcVersionMismatch<'a> { pub rustc_version: String, pub current_version: &'a str, } #[derive(Diagnostic)] -#[diag(driver_rlink_no_a_file)] +#[diag(driver_impl_rlink_no_a_file)] pub(crate) struct RlinkNotAFile; #[derive(Diagnostic)] -#[diag(driver_unpretty_dump_fail)] +#[diag(driver_impl_unpretty_dump_fail)] pub(crate) struct UnprettyDumpFail { pub path: String, pub err: String, } #[derive(Diagnostic)] -#[diag(driver_ice)] +#[diag(driver_impl_ice)] pub(crate) struct Ice; #[derive(Diagnostic)] -#[diag(driver_ice_bug_report)] +#[diag(driver_impl_ice_bug_report)] pub(crate) struct IceBugReport<'a> { pub bug_report_url: &'a str, } #[derive(Diagnostic)] -#[diag(driver_ice_version)] +#[diag(driver_impl_ice_version)] pub(crate) struct IceVersion<'a> { pub version: &'a str, pub triple: &'a str, } #[derive(Diagnostic)] -#[diag(driver_ice_flags)] +#[diag(driver_impl_ice_flags)] pub(crate) struct IceFlags { pub flags: String, } #[derive(Diagnostic)] -#[diag(driver_ice_exclude_cargo_defaults)] +#[diag(driver_impl_ice_exclude_cargo_defaults)] pub(crate) struct IceExcludeCargoDefaults; diff --git a/compiler/rustc_error_messages/locales/en-US/driver.ftl b/compiler/rustc_error_messages/locales/en-US/driver.ftl index 79ffc82c6c67..f19b1ff64261 100644 --- a/compiler/rustc_error_messages/locales/en-US/driver.ftl +++ b/compiler/rustc_error_messages/locales/en-US/driver.ftl @@ -1,19 +1,19 @@ -driver_rlink_unable_to_read = failed to read rlink file: `{$err}` +driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}` -driver_rlink_wrong_file_type = The input does not look like a .rlink file +driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file -driver_rlink_empty_version_number = The input does not contain version number +driver_impl_rlink_empty_version_number = The input does not contain version number -driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` +driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` -driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` +driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` -driver_rlink_no_a_file = rlink must be a file +driver_impl_rlink_no_a_file = rlink must be a file -driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}` +driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}` -driver_ice = the compiler unexpectedly panicked. this is a bug. -driver_ice_bug_report = we would appreciate a bug report: {$bug_report_url} -driver_ice_version = rustc {$version} running on {$triple} -driver_ice_flags = compiler flags: {$flags} -driver_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden +driver_impl_ice = the compiler unexpectedly panicked. this is a bug. +driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} +driver_impl_ice_version = rustc {$version} running on {$triple} +driver_impl_ice_flags = compiler flags: {$flags} +driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden From 2b8f8922ee5852f97e92082b209c0f4d940a6edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Feb 2023 07:47:39 +0100 Subject: [PATCH 044/137] Remove unneeded extern crate --- compiler/rustc_driver/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 195fc71b649d..4eabba575f42 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1,7 +1,4 @@ // This crate is intentionally empty and a rexport of `rustc_driver_impl` to allow the code in // `rustc_driver_impl` to be compiled in parallel with other crates. -#![allow(unused_extern_crates)] -extern crate rustc_driver_impl; - pub use rustc_driver_impl::*; From 9fe8ae792e4efd59ea37116a44391b4abdd2d7be Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 1 Feb 2023 10:42:20 +0000 Subject: [PATCH 045/137] Rename `rust_2015` => `is_rust_2015` --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_resolve/src/build_reduced_graph.rs | 6 +++--- compiler/rustc_resolve/src/diagnostics.rs | 8 +++++--- compiler/rustc_resolve/src/ident.rs | 5 +++-- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_session/src/session.rs | 4 ++-- compiler/rustc_span/src/edition.rs | 2 +- compiler/rustc_span/src/lib.rs | 4 ++-- 11 files changed, 21 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index fa8567eac609..d7767efa9841 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -131,7 +131,7 @@ pub fn print_crate<'a>( // Currently, in Rust 2018 we don't have `extern crate std;` at the crate // root, so this is not needed, and actually breaks things. - if edition.rust_2015() { + if edition.is_rust_2015() { // `#![no_std]` let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP); s.print_attribute(&fake_attr); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 81fd084ccb38..628e9d88cf1d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2247,7 +2247,7 @@ impl<'a> Parser<'a> { let ext = self.parse_extern(case); if let Async::Yes { span, .. } = asyncness { - if span.rust_2015() { + if span.is_rust_2015() { self.sess.emit_err(AsyncFnIn2015 { span, help: HelpUseLatestEdition::new() }); } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306cbcff149f..ba16be29f4ee 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -673,7 +673,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (!self.token.uninterpolated_span().rust_2015() + && (!self.token.uninterpolated_span().is_rust_2015() || self.look_ahead(1, |t| { (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star)) && !can_continue_type_after_non_fn_ident(t) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 84421dc1f622..2fb62ce53ba6 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -265,7 +265,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let ident = path.segments.get(0).expect("empty path in visibility").ident; let crate_root = if ident.is_path_segment_keyword() { None - } else if ident.span.rust_2015() { + } else if ident.span.is_rust_2015() { Some(Segment::from_ident(Ident::new( kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()), @@ -435,10 +435,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // appears, so imports in braced groups can have roots prepended independently. let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob); let crate_root = match prefix_iter.peek() { - Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => { Some(seg.ident.span.ctxt()) } - None if is_glob && use_tree.span.rust_2015() => Some(use_tree.span.ctxt()), + None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()), _ => None, } .map(|ctxt| { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3bf041cebcb8..a08ae0f184bb 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -462,7 +462,9 @@ impl<'a> Resolver<'a> { let first_name = match path.get(0) { // In the 2018 edition this lint is a hard error, so nothing to do - Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name, + Some(seg) if seg.ident.span.is_rust_2015() && self.session.is_rust_2015() => { + seg.ident.name + } _ => return, }; @@ -1717,7 +1719,7 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )), ) - } else if self.session.rust_2015() { + } else if self.session.is_rust_2015() { ( format!("maybe a missing crate `{ident}`?"), Some(( @@ -1996,7 +1998,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { mut path: Vec, parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Option)> { - if path[1].ident.span.rust_2015() { + if path[1].ident.span.is_rust_2015() { return None; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1c985d43658a..d03ccf256fad 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -85,7 +85,7 @@ impl<'a> Resolver<'a> { // 4c. Standard library prelude (de-facto closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled). - let rust_2015 = ctxt.edition().rust_2015(); + let rust_2015 = ctxt.edition().is_rust_2015(); let (ns, macro_kind, is_absolute_path) = match scope_set { ScopeSet::All(ns, _) => (ns, None, false), ScopeSet::AbsolutePath(ns) => (ns, None, true), @@ -1397,7 +1397,8 @@ impl<'a> Resolver<'a> { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } - if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() { + if name == kw::PathRoot && ident.span.is_rust_2015() && self.session.rust_2018() + { // `::a::b` from 2015 macro on 2018 global edition module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); continue; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 83932c089b31..3ca10ac50baa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2145,7 +2145,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let segments = &use_tree.prefix.segments; if !segments.is_empty() { let ident = segments[0].ident; - if ident.is_path_segment_keyword() || ident.span.rust_2015() { + if ident.is_path_segment_keyword() || ident.span.is_rust_2015() { return; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 37beff37c1fb..cee0a7f3c203 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1343,7 +1343,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { "!", Applicability::MaybeIncorrect, ); - if path_str == "try" && span.rust_2015() { + if path_str == "try" && span.is_rust_2015() { err.note("if you want the `try` keyword, you need Rust 2018 or later"); } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 746e0f169bcf..dbd419c1406f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -919,8 +919,8 @@ impl Session { } /// Is this edition 2015? - pub fn rust_2015(&self) -> bool { - self.edition().rust_2015() + pub fn is_rust_2015(&self) -> bool { + self.edition().is_rust_2015() } /// Are we allowed to use features from the Rust 2018 edition? diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index e66ec0790434..f16db69aae23 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -77,7 +77,7 @@ impl Edition { } /// Is this edition 2015? - pub fn rust_2015(self) -> bool { + pub fn is_rust_2015(self) -> bool { self == Edition::Edition2015 } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 006102a5f2fc..e095cf3fda20 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -705,8 +705,8 @@ impl Span { } #[inline] - pub fn rust_2015(self) -> bool { - self.edition().rust_2015() + pub fn is_rust_2015(self) -> bool { + self.edition().is_rust_2015() } #[inline] From a7f97a7689197e5d87fd26390cfdb387185a7376 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 1 Feb 2023 10:44:59 +0000 Subject: [PATCH 046/137] Use `rust_2018` instead of `!is_rust_2015` --- compiler/rustc_parse/src/parser/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index ba16be29f4ee..18aa20cee421 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -673,7 +673,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (!self.token.uninterpolated_span().is_rust_2015() + && (self.token.uninterpolated_span().rust_2018() || self.look_ahead(1, |t| { (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star)) && !can_continue_type_after_non_fn_ident(t) From 4614e5b5bf1331907bf3baf70cf0eb705f2959e9 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 2 Feb 2023 10:09:48 +0000 Subject: [PATCH 047/137] llvm-wrapper: adapt for LLVM API changes Adapts the wrapper for https://github.com/llvm/llvm-project/commit/516e301752560311d2cd8c2b549493eb0f98d01b, where the constructor of PGOOptions gained a new FileSystem argument. Adapted to use the real file system, similarly to the changes inside of LLVM: https://github.com/llvm/llvm-project/commit/516e301752560311d2cd8c2b549493eb0f98d01b#diff-f409934ba27ad86494f3012324e9a3995b56e0743609ded7a387ba62bbf5edb0R236 --- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index f728bff0e3b9..15a4273fc591 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -21,6 +21,9 @@ #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" +#if LLVM_VERSION_GE(17, 0) +#include "llvm/Support/VirtualFileSystem.h" +#endif #include "llvm/Support/Host.h" #if LLVM_VERSION_LT(14, 0) #include "llvm/Support/TargetRegistry.h" @@ -651,21 +654,40 @@ LLVMRustOptimize( Optional PGOOpt; #else std::optional PGOOpt; +#endif +#if LLVM_VERSION_GE(17, 0) + auto FS = vfs::getRealFileSystem(); #endif if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOGenPath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::IRInstr, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (PGOUsePath) { assert(!PGOSampleUsePath); - PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOUsePath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::IRUse, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (PGOSampleUsePath) { - PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions(PGOSampleUsePath, "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::SampleUse, PGOOptions::NoCSAction, + DebugInfoForProfiling); } else if (DebugInfoForProfiling) { - PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction, - PGOOptions::NoCSAction, DebugInfoForProfiling); + PGOOpt = PGOOptions("", "", "", +#if LLVM_VERSION_GE(17, 0) + FS, +#endif + PGOOptions::NoAction, PGOOptions::NoCSAction, + DebugInfoForProfiling); } PassBuilder PB(TM, PTO, PGOOpt, &PIC); From f922c8395d1cfc54c67cbd645f8456a13fb0189f Mon Sep 17 00:00:00 2001 From: Mads Ravn Date: Sun, 8 Jan 2023 23:48:41 +0100 Subject: [PATCH 048/137] PR fixing wrong order of format parameters in strings. Issue #106572 Adding Adding Fixing small issues for PR Adding tests Removing unused binding Changing the wording on note Fixing PR comment --- compiler/rustc_parse_format/src/lib.rs | 29 +++++++++- tests/ui/fmt/format-string-wrong-order.rs | 15 ++++++ tests/ui/fmt/format-string-wrong-order.stderr | 54 +++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 tests/ui/fmt/format-string-wrong-order.rs create mode 100644 tests/ui/fmt/format-string-wrong-order.stderr diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 1eb227503f24..099cbd31917f 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -271,7 +271,13 @@ impl<'a> Iterator for Parser<'a> { ); } } else { - self.suggest_positional_arg_instead_of_captured_arg(arg); + if let Some(&(_, maybe)) = self.cur.peek() { + if maybe == '?' { + self.suggest_format(); + } else { + self.suggest_positional_arg_instead_of_captured_arg(arg); + } + } } Some(NextArgument(Box::new(arg))) } @@ -823,6 +829,27 @@ impl<'a> Parser<'a> { if found { Some(cur) } else { None } } + fn suggest_format(&mut self) { + if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) { + let word = self.word(); + let _end = self.current_pos(); + let pos = self.to_span_index(pos); + self.errors.insert( + 0, + ParseError { + description: "expected format parameter to occur after `:`".to_owned(), + note: Some( + format!("`?` comes after `:`, try `{}:{}` instead", word, "?").to_owned(), + ), + label: "expected `?` to occur after `:`".to_owned(), + span: pos.to(pos), + secondary_label: None, + should_be_replaced_with_positional_argument: false, + }, + ); + } + } + fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) { if let Some(end) = self.consume_pos('.') { let byte_pos = self.to_span_index(end); diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs new file mode 100644 index 000000000000..0bad54023965 --- /dev/null +++ b/tests/ui/fmt/format-string-wrong-order.rs @@ -0,0 +1,15 @@ +fn main() { + let bar = 3; + format!("{?:}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{?:bar}"); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{?:?}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` + format!("{??}", bar); + //~^ ERROR invalid format string: expected `'}'`, found `'?'` + format!("{?;bar}"); + //~^ ERROR invalid format string: expected `'}'`, found `'?'` + format!("{?:#?}", bar); + //~^ ERROR invalid format string: expected format parameter to occur after `:` +} diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr new file mode 100644 index 000000000000..461af354a4e1 --- /dev/null +++ b/tests/ui/fmt/format-string-wrong-order.stderr @@ -0,0 +1,54 @@ +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:3:15 + | +LL | format!("{?:}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:5:15 + | +LL | format!("{?:bar}"); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `bar:?` instead + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:7:15 + | +LL | format!("{?:?}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: invalid format string: expected `'}'`, found `'?'` + --> $DIR/format-string-wrong-order.rs:9:15 + | +LL | format!("{??}", bar); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'?'` + --> $DIR/format-string-wrong-order.rs:11:15 + | +LL | format!("{?;bar}"); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected format parameter to occur after `:` + --> $DIR/format-string-wrong-order.rs:13:15 + | +LL | format!("{?:#?}", bar); + | ^ expected `?` to occur after `:` in format string + | + = note: `?` comes after `:`, try `:?` instead + +error: aborting due to 6 previous errors + From 4ab75de934935f59f243ab64a641e28aa89e6fcd Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 30 Jan 2023 23:47:10 +0000 Subject: [PATCH 049/137] Improve diagnostic for missing space in range pattern --- .../rustc_error_messages/locales/en-US/parse.ftl | 5 +++-- compiler/rustc_parse/src/errors.rs | 9 +++------ compiler/rustc_parse/src/parser/expr.rs | 8 ++++++++ compiler/rustc_parse/src/parser/pat.rs | 2 +- ...half-open-range-pats-inclusive-match-arrow.rs | 5 +++-- ...-open-range-pats-inclusive-match-arrow.stderr | 16 ++++++---------- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 21cf4bd789c7..4c45ccf6674d 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -203,8 +203,9 @@ parse_inclusive_range_extra_equals = unexpected `=` after inclusive range .suggestion_remove_eq = use `..=` instead .note = inclusive ranges end with a single equals sign (`..=`) -parse_inclusive_range_match_arrow = unexpected `=>` after open range - .suggestion_add_space = add a space between the pattern and `=>` +parse_inclusive_range_match_arrow = unexpected `>` after inclusive range + .label = this is parsed as an inclusive range `..=` + .suggestion = add a space between the pattern and `=>` parse_inclusive_range_no_end = inclusive range with no end .suggestion_open_range = use `..` instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 145611923ff1..dcda518f47c4 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -668,13 +668,10 @@ pub(crate) struct InclusiveRangeExtraEquals { #[diag(parse_inclusive_range_match_arrow)] pub(crate) struct InclusiveRangeMatchArrow { #[primary_span] + pub arrow: Span, + #[label] pub span: Span, - #[suggestion( - suggestion_add_space, - style = "verbose", - code = " ", - applicability = "machine-applicable" - )] + #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")] pub after_pat: Span, } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b7a023868fce..3d42a9dcbbea 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2717,6 +2717,14 @@ impl<'a> Parser<'a> { ); err.emit(); this.bump(); + } else if matches!( + (&this.prev_token.kind, &this.token.kind), + (token::DotDotEq, token::Gt) + ) { + // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`, + // so we supress the error here + err.delay_as_bug(); + this.bump(); } else { return Err(err); } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 88c75fd81e75..4a2bd3fc5307 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -744,7 +744,7 @@ impl<'a> Parser<'a> { } token::Gt if no_space => { let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi(); - self.sess.emit_err(InclusiveRangeMatchArrow { span, after_pat }); + self.sess.emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span, after_pat }); } _ => { self.sess.emit_err(InclusiveRangeNoEnd { span }); diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs index 7ba2b6d857cd..30173b1b4be0 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs @@ -2,7 +2,8 @@ fn main() { let x = 42; match x { 0..=73 => {}, - 74..=> {}, //~ ERROR unexpected `=>` after open range - //~^ ERROR expected one of `=>`, `if`, or `|`, found `>` + 74..=> {}, + //~^ ERROR unexpected `>` after inclusive range + //~| NOTE this is parsed as an inclusive range `..=` } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr index 9ba6d15113cd..cb7f998df7a5 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr @@ -1,19 +1,15 @@ -error: unexpected `=>` after open range - --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:11 +error: unexpected `>` after inclusive range + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14 | LL | 74..=> {}, - | ^^^ + | ---^ + | | + | this is parsed as an inclusive range `..=` | help: add a space between the pattern and `=>` | LL | 74.. => {}, | + -error: expected one of `=>`, `if`, or `|`, found `>` - --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14 - | -LL | 74..=> {}, - | ^ expected one of `=>`, `if`, or `|` - -error: aborting due to 2 previous errors +error: aborting due to previous error From 7f9cfce18e9b4e01af4dd3fa00331bb9e364dcf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 2 Feb 2023 15:02:18 +0100 Subject: [PATCH 050/137] Make timer hierarchical --- src/ci/stage-build.py | 160 +++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 55 deletions(-) diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py index 775478bcbab4..662c9e36694c 100644 --- a/src/ci/stage-build.py +++ b/src/ci/stage-build.py @@ -15,10 +15,9 @@ import sys import time import traceback import urllib.request -from collections import OrderedDict from io import StringIO from pathlib import Path -from typing import Callable, Dict, Iterable, List, Optional, Union +from typing import Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union PGO_HOST = os.environ["PGO_HOST"] @@ -204,57 +203,105 @@ class WindowsPipeline(Pipeline): return False +def get_timestamp() -> float: + return time.time() + + +Duration = float +TimerSection = Union[Duration, "Timer"] + + +def iterate_sections(section: TimerSection, name: str, level: int = 0) -> Iterator[Tuple[int, str, Duration]]: + """ + Hierarchically iterate the sections of a timer, in a depth-first order. + """ + if isinstance(section, Duration): + yield (level, name, section) + elif isinstance(section, Timer): + yield (level, name, section.total_duration()) + for (child_name, child_section) in section.sections: + yield from iterate_sections(child_section, child_name, level=level + 1) + else: + assert False + + class Timer: - def __init__(self): - # We want this dictionary to be ordered by insertion. - # We use `OrderedDict` for compatibility with older Python versions. - self.stages = OrderedDict() + def __init__(self, parent_names: Tuple[str, ...] = ()): + self.sections: List[Tuple[str, TimerSection]] = [] + self.section_active = False + self.parent_names = parent_names @contextlib.contextmanager - def stage(self, name: str): - assert name not in self.stages + def section(self, name: str) -> "Timer": + assert not self.section_active + self.section_active = True - start = time.time() + start = get_timestamp() exc = None + + child_timer = Timer(parent_names=self.parent_names + (name, )) + full_name = " > ".join(child_timer.parent_names) try: - LOGGER.info(f"Stage `{name}` starts") - yield + LOGGER.info(f"Section `{full_name}` starts") + yield child_timer except BaseException as exception: exc = exception raise finally: - end = time.time() + end = get_timestamp() duration = end - start - self.stages[name] = duration - if exc is None: - LOGGER.info(f"Stage `{name}` ended: OK ({duration:.2f}s)") + + if child_timer.has_children(): + self.sections.append((name, child_timer)) else: - LOGGER.info(f"Stage `{name}` ended: FAIL ({duration:.2f}s)") + self.sections.append((name, duration)) + if exc is None: + LOGGER.info(f"Section `{full_name}` ended: OK ({duration:.2f}s)") + else: + LOGGER.info(f"Section `{full_name}` ended: FAIL ({duration:.2f}s)") + self.section_active = False + + def total_duration(self) -> Duration: + duration = 0 + for (_, section) in self.sections: + if isinstance(section, Duration): + duration += section + else: + duration += section.total_duration() + return duration + + def has_children(self) -> bool: + return len(self.sections) > 0 def print_stats(self): - total_duration = sum(self.stages.values()) + rows = [] + for (child_name, child_section) in self.sections: + for (level, name, duration) in iterate_sections(child_section, child_name, level=0): + label = f"{' ' * level}{name}:" + rows.append((label, duration)) + + # Empty row + rows.append(("", "")) total_duration_label = "Total duration:" + total_duration = self.total_duration() + rows.append((total_duration_label, humantime(total_duration))) - # 1 is for ":", 2 is horizontal space - max_label_length = max(16, max( - len(label) for label in list(self.stages.keys()) + [total_duration_label[:-1]] - )) + 1 + 2 + space_after_label = 2 + max_label_length = max(16, max(len(label) for (label, _) in rows)) + space_after_label table_width = max_label_length + 23 divider = "-" * table_width with StringIO() as output: print(divider, file=output) - for (name, duration) in self.stages.items(): - pct = (duration / total_duration) * 100 - name_str = f"{name}:" - print(f"{name_str:<{max_label_length}} {duration:>12.2f}s ({pct:>5.2f}%)", - file=output) - - print(file=output) - print(f"{total_duration_label:<{max_label_length}} {humantime(total_duration):>22}", - file=output) + for (label, duration) in rows: + if isinstance(duration, Duration): + pct = (duration / total_duration) * 100 + value = f"{duration:>12.2f}s ({pct:>5.2f}%)" + else: + value = f"{duration:>{len(total_duration_label) + 7}}" + print(f"{label:<{max_label_length}} {value}", file=output) print(divider, file=output, end="") LOGGER.info(f"Timer results\n{output.getvalue()}") @@ -274,7 +321,7 @@ def change_cwd(dir: Path): os.chdir(cwd) -def humantime(time_s: int) -> str: +def humantime(time_s: float) -> str: hours = time_s // 3600 time_s = time_s % 3600 minutes = time_s // 60 @@ -609,15 +656,16 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L pipeline.build_rustc_perf() # Stage 1: Build rustc + PGO instrumented LLVM - with timer.stage("Build rustc (LLVM PGO)"): - build_rustc(pipeline, args=[ - "--llvm-profile-generate" - ], env=dict( - LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p") - )) + with timer.section("Stage 1 (LLVM PGO)") as stage1: + with stage1.section("Build rustc and LLVM"): + build_rustc(pipeline, args=[ + "--llvm-profile-generate" + ], env=dict( + LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p") + )) - with timer.stage("Gather profiles (LLVM PGO)"): - gather_llvm_profiles(pipeline) + with stage1.section("Gather profiles"): + gather_llvm_profiles(pipeline) clear_llvm_files(pipeline) final_build_args += [ @@ -626,14 +674,15 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L ] # Stage 2: Build PGO instrumented rustc + LLVM - with timer.stage("Build rustc (rustc PGO)"): - build_rustc(pipeline, args=[ - "--rust-profile-generate", - pipeline.rustc_profile_dir_root() - ]) + with timer.section("Stage 2 (rustc PGO)") as stage2: + with stage2.section("Build rustc and LLVM"): + build_rustc(pipeline, args=[ + "--rust-profile-generate", + pipeline.rustc_profile_dir_root() + ]) - with timer.stage("Gather profiles (rustc PGO)"): - gather_rustc_profiles(pipeline) + with stage2.section("Gather profiles"): + gather_rustc_profiles(pipeline) clear_llvm_files(pipeline) final_build_args += [ @@ -643,14 +692,15 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L # Stage 3: Build rustc + BOLT instrumented LLVM if pipeline.supports_bolt(): - with timer.stage("Build rustc (LLVM BOLT)"): - build_rustc(pipeline, args=[ - "--llvm-profile-use", - pipeline.llvm_profile_merged_file(), - "--llvm-bolt-profile-generate", - ]) - with timer.stage("Gather profiles (LLVM BOLT)"): - gather_llvm_bolt_profiles(pipeline) + with timer.section("Stage 3 (LLVM BOLT)") as stage3: + with stage3.section("Build rustc and LLVM"): + build_rustc(pipeline, args=[ + "--llvm-profile-use", + pipeline.llvm_profile_merged_file(), + "--llvm-bolt-profile-generate", + ]) + with stage3.section("Gather profiles"): + gather_llvm_bolt_profiles(pipeline) clear_llvm_files(pipeline) final_build_args += [ @@ -659,7 +709,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L ] # Stage 4: Build PGO optimized rustc + PGO/BOLT optimized LLVM - with timer.stage("Final build"): + with timer.section("Stage 4 (final build)"): cmd(final_build_args) From 227b2858da8aac6791e86a86f938a652993e5ea3 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 2 Feb 2023 14:26:28 +0100 Subject: [PATCH 051/137] Retry opening proc-macro DLLs a few times on Windows. --- compiler/rustc_metadata/src/creader.rs | 42 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 653f2b39d3e7..44d6c587da3d 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -33,6 +33,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use proc_macro::bridge::client::ProcMacro; use std::ops::Fn; use std::path::Path; +use std::time::Duration; use std::{cmp, env}; #[derive(Clone)] @@ -689,8 +690,7 @@ impl<'a> CrateLoader<'a> { ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); - let lib = unsafe { libloading::Library::new(path) } - .map_err(|err| CrateError::DlOpen(err.to_string()))?; + let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?; let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) } @@ -1093,3 +1093,41 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec { visit::walk_crate(&mut f, krate); f.spans } + +// On Windows the compiler would sometimes intermittently fail to open the +// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the +// system still holds a lock on the file, so we retry a few times before calling it +// an error. +fn load_dylib(path: &Path, max_attempts: usize) -> Result { + assert!(max_attempts > 0); + + let mut last_error = None; + + for attempt in 0..max_attempts { + match unsafe { libloading::Library::new(&path) } { + Ok(lib) => { + if attempt > 0 { + debug!( + "Loaded proc-macro `{}` after {} attempts.", + path.display(), + attempt + 1 + ); + } + return Ok(lib); + } + Err(err) => { + // Only try to recover from this specific error. + if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { + return Err(err.to_string()); + } + + last_error = Some(err); + std::thread::sleep(Duration::from_millis(100)); + debug!("Failed to load proc-macro `{}`. Retrying.", path.display()); + } + } + } + + debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts); + Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts)) +} From e6b84eb7973fb751744a1802cee404254d67673e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 7 Jan 2023 22:17:00 +0000 Subject: [PATCH 052/137] Suggest `move` in nested closure when appropriate Fix #64008. --- .../src/diagnostics/region_errors.rs | 28 +++++++---------- compiler/rustc_middle/src/ty/sty.rs | 22 +++++++++++++ ...95079-missing-move-in-nested-closure.fixed | 26 ++++++++++++++++ ...ue-95079-missing-move-in-nested-closure.rs | 12 +++++++ ...5079-missing-move-in-nested-closure.stderr | 31 ++++++++++++++++--- 5 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 87db08ef5b51..7901a5046aba 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -583,10 +583,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let err = FnMutError { span: *span, ty_err: match output_ty.kind() { - ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span }, ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => { FnMutReturnTypeErr::ReturnAsyncBlock { span: *span } } + _ if output_ty.contains_closure() => { + FnMutReturnTypeErr::ReturnClosure { span: *span } + } _ => FnMutReturnTypeErr::ReturnRef { span: *span }, }, }; @@ -997,7 +999,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) { let map = self.infcx.tcx.hir(); let body_id = map.body_owned_by(self.mir_def_id()); - let expr = &map.body(body_id).value; + let expr = &map.body(body_id).value.peel_blocks(); let mut closure_span = None::; match expr.kind { hir::ExprKind::MethodCall(.., args, _) => { @@ -1012,20 +1014,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } } - hir::ExprKind::Block(blk, _) => { - if let Some(expr) = blk.expr { - // only when the block is a closure - if let hir::ExprKind::Closure(hir::Closure { - capture_clause: hir::CaptureBy::Ref, - body, - .. - }) = expr.kind - { - let body = map.body(*body); - if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) { - closure_span = Some(expr.span.shrink_to_lo()); - } - } + hir::ExprKind::Closure(hir::Closure { + capture_clause: hir::CaptureBy::Ref, + body, + .. + }) => { + let body = map.body(*body); + if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) { + closure_span = Some(expr.span.shrink_to_lo()); } } _ => {} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 060d864389cb..98d6b6835636 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2043,6 +2043,28 @@ impl<'tcx> Ty<'tcx> { cf.is_break() } + /// Checks whether a type recursively contains any closure + /// + /// Example: `Option<[closure@file.rs:4:20]>` returns true + pub fn contains_closure(self) -> bool { + struct ContainsClosureVisitor; + + impl<'tcx> TypeVisitor<'tcx> for ContainsClosureVisitor { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if let ty::Closure(_, _) = t.kind() { + ControlFlow::Break(()) + } else { + t.super_visit_with(self) + } + } + } + + let cf = self.visit_with(&mut ContainsClosureVisitor); + cf.is_break() + } + /// Returns the type and mutability of `*ty`. /// /// The parameter `explicit` indicates if this is an *explicit* dereference. diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed new file mode 100644 index 000000000000..1a08470064cd --- /dev/null +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed @@ -0,0 +1,26 @@ +// run-rustfix +#![allow(dead_code, path_statements)] +fn foo1(s: &str) -> impl Iterator + '_ { + None.into_iter() + .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s))) + //~^ ERROR captured variable cannot escape `FnMut` closure body + //~| HELP consider adding 'move' keyword before the nested closure +} + +fn foo2(s: &str) -> impl Sized + '_ { + move |()| s.chars().map(move |c| format!("{}{}", c, s)) + //~^ ERROR lifetime may not live long enough + //~| HELP consider adding 'move' keyword before the nested closure +} + +pub struct X; +pub fn foo3<'a>( + bar: &'a X, +) -> impl Iterator + 'a { + Some(()).iter().flat_map(move |()| { + Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape + //~^ HELP consider adding 'move' keyword before the nested closure + }) +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs index 95847d8d301a..b93292e3589d 100644 --- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(dead_code, path_statements)] fn foo1(s: &str) -> impl Iterator + '_ { None.into_iter() .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) @@ -11,4 +13,14 @@ fn foo2(s: &str) -> impl Sized + '_ { //~| HELP consider adding 'move' keyword before the nested closure } +pub struct X; +pub fn foo3<'a>( + bar: &'a X, +) -> impl Iterator + 'a { + Some(()).iter().flat_map(move |()| { + Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape + //~^ HELP consider adding 'move' keyword before the nested closure + }) +} + fn main() {} diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr index 2eae614a2f59..776c338deacf 100644 --- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr @@ -1,5 +1,5 @@ error: captured variable cannot escape `FnMut` closure body - --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29 + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29 | LL | fn foo1(s: &str) -> impl Iterator + '_ { | - variable defined here @@ -7,7 +7,7 @@ LL | None.into_iter() LL | .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) | - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | - | | returns a reference to a captured variable which escapes the closure body + | | returns a closure that contains a reference to a captured variable, which then escapes the closure body | | variable captured here | inferred to be a `FnMut` closure | @@ -19,12 +19,12 @@ LL | .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s))) | ++++ error: lifetime may not live long enough - --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15 + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15 | LL | move |()| s.chars().map(|c| format!("{}{}", c, s)) | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2` + | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2` | lifetime `'1` represents this closure's body | = note: closure implements `Fn`, so references to captured variables can't escape the closure @@ -33,5 +33,26 @@ help: consider adding 'move' keyword before the nested closure LL | move |()| s.chars().map(move |c| format!("{}{}", c, s)) | ++++ -error: aborting due to 2 previous errors +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9 + | +LL | bar: &'a X, + | --- variable defined here +LL | ) -> impl Iterator + 'a { +LL | Some(()).iter().flat_map(move |()| { + | - inferred to be a `FnMut` closure +LL | Some(()).iter().map(|()| { bar; }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^ + | | | + | | variable captured here + | returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | Some(()).iter().map(move |()| { bar; }) + | ++++ + +error: aborting due to 3 previous errors From fe84cecf601522ed010fe35033b87a6ba8844c7d Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 2 Feb 2023 23:43:07 +0800 Subject: [PATCH 053/137] fix #107590, Fix benchmarks in library/core with black_box --- library/core/benches/char/methods.rs | 40 ++++++++++++------- .../benches/num/flt2dec/strategy/dragon.rs | 18 ++++----- .../benches/num/flt2dec/strategy/grisu.rs | 18 ++++----- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs index 9408f83c32f7..5d4df1ac8bd5 100644 --- a/library/core/benches/char/methods.rs +++ b/library/core/benches/char/methods.rs @@ -1,26 +1,26 @@ -use test::Bencher; +use test::{black_box, Bencher}; const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9']; const RADIX: [u32; 5] = [2, 8, 10, 16, 32]; #[bench] fn bench_to_digit_radix_2(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min()) } #[bench] fn bench_to_digit_radix_10(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min()) } #[bench] fn bench_to_digit_radix_16(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min()) } #[bench] fn bench_to_digit_radix_36(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min()) } #[bench] @@ -31,47 +31,59 @@ fn bench_to_digit_radix_var(b: &mut Bencher) { .cycle() .zip(RADIX.iter().cycle()) .take(10_000) - .map(|(c, radix)| c.to_digit(*radix)) + .map(|(c, radix)| black_box(c).to_digit(*radix)) .min() }) } #[bench] fn bench_to_ascii_uppercase(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min()) } #[bench] fn bench_to_ascii_lowercase(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min()) + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min()) } #[bench] fn bench_ascii_mix_to_uppercase(b: &mut Bencher) { - b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_ascii_mix_to_lowercase(b: &mut Bencher) { - b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } #[bench] fn bench_ascii_char_to_uppercase(b: &mut Bencher) { - b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_ascii_char_to_lowercase(b: &mut Bencher) { - b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } #[bench] fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) { - b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count()) + b.iter(|| { + (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + }) } #[bench] fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) { - b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count()) + b.iter(|| { + (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + }) } diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs index 319b9773e49f..377c99effd03 100644 --- a/library/core/benches/num/flt2dec/strategy/dragon.rs +++ b/library/core/benches/num/flt2dec/strategy/dragon.rs @@ -1,14 +1,14 @@ use super::super::*; use core::num::flt2dec::strategy::dragon::*; use std::mem::MaybeUninit; -use test::Bencher; +use test::{black_box, Bencher}; #[bench] fn bench_small_shortest(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -17,7 +17,7 @@ fn bench_big_shortest(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -26,7 +26,7 @@ fn bench_small_exact_3(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -35,7 +35,7 @@ fn bench_big_exact_3(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -44,7 +44,7 @@ fn bench_small_exact_12(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -53,7 +53,7 @@ fn bench_big_exact_12(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -62,7 +62,7 @@ fn bench_small_exact_inf(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -71,6 +71,6 @@ fn bench_big_exact_inf(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs index 8e47a046cdea..6bea5e55d37b 100644 --- a/library/core/benches/num/flt2dec/strategy/grisu.rs +++ b/library/core/benches/num/flt2dec/strategy/grisu.rs @@ -1,7 +1,7 @@ use super::super::*; use core::num::flt2dec::strategy::grisu::*; use std::mem::MaybeUninit; -use test::Bencher; +use test::{black_box, Bencher}; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { @@ -15,7 +15,7 @@ fn bench_small_shortest(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -24,7 +24,7 @@ fn bench_big_shortest(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS]; b.iter(|| { - format_shortest(&decoded, &mut buf); + format_shortest(black_box(&decoded), &mut buf); }); } @@ -33,7 +33,7 @@ fn bench_small_exact_3(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -42,7 +42,7 @@ fn bench_big_exact_3(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 3]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -51,7 +51,7 @@ fn bench_small_exact_12(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -60,7 +60,7 @@ fn bench_big_exact_12(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 12]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -69,7 +69,7 @@ fn bench_small_exact_inf(b: &mut Bencher) { let decoded = decode_finite(3.141592f64); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } @@ -78,6 +78,6 @@ fn bench_big_exact_inf(b: &mut Bencher) { let decoded = decode_finite(f64::MAX); let mut buf = [MaybeUninit::new(0); 1024]; b.iter(|| { - format_exact(&decoded, &mut buf, i16::MIN); + format_exact(black_box(&decoded), &mut buf, i16::MIN); }); } From 0ba687a95ee64a013b71ca7b606896e60c6182f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 Feb 2023 16:42:21 +0000 Subject: [PATCH 054/137] Parse and recover from type ascription in patterns --- .../rustc_parse/src/parser/diagnostics.rs | 51 +++++++++--- .../issues/issue-87086-colon-path-sep.rs | 1 - .../issues/issue-87086-colon-path-sep.stderr | 81 +++++++++++++------ tests/ui/parser/type-ascription-in-pattern.rs | 16 ++++ .../parser/type-ascription-in-pattern.stderr | 54 +++++++++++++ 5 files changed, 164 insertions(+), 39 deletions(-) create mode 100644 tests/ui/parser/type-ascription-in-pattern.rs create mode 100644 tests/ui/parser/type-ascription-in-pattern.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 16d5edfd303a..cd9d85b1d919 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2405,26 +2405,42 @@ impl<'a> Parser<'a> { if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) { + let mut snapshot_type = self.create_snapshot_for_diagnostic(); + snapshot_type.bump(); // `:` + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else { + return first_pat; + }; + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(span, PatKind::Wild); + err.emit(); + } + } return first_pat; } // The pattern looks like it might be a path with a `::` -> `:` typo: // `match foo { bar:baz => {} }` - let span = self.token.span; + let colon_span = self.token.span; // We only emit "unexpected `:`" error here if we can successfully parse the // whole pattern correctly in that case. - let snapshot = self.create_snapshot_for_diagnostic(); + let mut snapshot_pat = self.create_snapshot_for_diagnostic(); + let mut snapshot_type = self.create_snapshot_for_diagnostic(); // Create error for "unexpected `:`". match self.expected_one_of_not_found(&[], &[]) { Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { + // Skip the `:`. + snapshot_pat.bump(); + snapshot_type.bump(); + match snapshot_pat.parse_pat_no_top_alt(expected) { Err(inner_err) => { - // Carry on as if we had not done anything, callers will emit a - // reasonable error. inner_err.cancel(); - err.cancel(); - self.restore_snapshot(snapshot); } Ok(mut pat) => { // We've parsed the rest of the pattern. @@ -2488,8 +2504,8 @@ impl<'a> Parser<'a> { _ => {} } if show_sugg { - err.span_suggestion( - span, + err.span_suggestion_verbose( + colon_span.until(self.look_ahead(1, |t| t.span)), "maybe write a path separator here", "::", Applicability::MaybeIncorrect, @@ -2497,13 +2513,24 @@ impl<'a> Parser<'a> { } else { first_pat = self.mk_pat(new_span, PatKind::Wild); } - err.emit(); + self.restore_snapshot(snapshot_pat); } } + match snapshot_type.parse_ty() { + Err(inner_err) => { + inner_err.cancel(); + } + Ok(ty) => { + err.span_label(ty.span, "specifying the type of a pattern isn't supported"); + self.restore_snapshot(snapshot_type); + let new_span = first_pat.span.to(ty.span); + first_pat = self.mk_pat(new_span, PatKind::Wild); + } + } + err.emit(); } _ => { // Carry on as if we had not done anything. This should be unreachable. - self.restore_snapshot(snapshot); } }; first_pat diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index 0b7b67496d6f..e1ea38f2795d 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -68,7 +68,6 @@ fn main() { Foo:Bar::Baz => {} //~^ ERROR: expected one of //~| HELP: maybe write a path separator here - //~| ERROR: failed to resolve: `Bar` is a variant, not a module } match myfoo { Foo::Bar => {} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 2050a16beb34..63b072ac4cdc 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:17:12 | LL | Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:23:17 | LL | qux::Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of 8 possible tokens - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Bar => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:29:12 | LL | qux:Foo::Baz => {} - | ^ + | ^-------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:35:12 | LL | qux: Foo::Baz if true => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | qux::Foo::Baz if true => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:40:15 | LL | if let Foo:Bar = f() { - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | if let Foo::Bar = f() { + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:48:16 | LL | ref qux: Foo::Baz => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | ref qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:57:16 | LL | mut qux: Foo::Baz => {} - | ^ + | ^ -------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | mut qux::Foo::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` --> $DIR/issue-87086-colon-path-sep.rs:68:12 | LL | Foo:Bar::Baz => {} - | ^ + | ^-------- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` + | +help: maybe write a path separator here + | +LL | Foo::Bar::Baz => {} + | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:75:12 + --> $DIR/issue-87086-colon-path-sep.rs:74:12 | LL | Foo:Bar => {} - | ^ + | ^--- specifying the type of a pattern isn't supported | | | expected one of `@` or `|` - | help: maybe write a path separator here: `::` - -error[E0433]: failed to resolve: `Bar` is a variant, not a module - --> $DIR/issue-87086-colon-path-sep.rs:68:13 | -LL | Foo:Bar::Baz => {} - | ^^^ `Bar` is a variant, not a module +help: maybe write a path separator here + | +LL | Foo::Bar => {} + | ~~ -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs new file mode 100644 index 000000000000..fec168afba1d --- /dev/null +++ b/tests/ui/parser/type-ascription-in-pattern.rs @@ -0,0 +1,16 @@ +fn foo(x: bool) -> i32 { + match x { + x: i32 => x, //~ ERROR expected + //~^ ERROR mismatched types + true => 42., + false => 0.333, + } +} + +fn main() { + match foo(true) { + 42: i32 => (), //~ ERROR expected + _: f64 => (), //~ ERROR expected + x: i32 => (), //~ ERROR expected + } +} diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr new file mode 100644 index 000000000000..091907549936 --- /dev/null +++ b/tests/ui/parser/type-ascription-in-pattern.stderr @@ -0,0 +1,54 @@ +error: expected one of `@` or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:3:10 + | +LL | x: i32 => x, + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `@` or `|` + | +help: maybe write a path separator here + | +LL | x::i32 => x, + | ~~ + +error: expected one of `...`, `..=`, `..`, or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:12:11 + | +LL | 42: i32 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `...`, `..=`, `..`, or `|` + +error: expected `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:13:10 + | +LL | _: f64 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected `|` + +error: expected one of `@` or `|`, found `:` + --> $DIR/type-ascription-in-pattern.rs:14:10 + | +LL | x: i32 => (), + | ^ --- specifying the type of a pattern isn't supported + | | + | expected one of `@` or `|` + | +help: maybe write a path separator here + | +LL | x::i32 => (), + | ~~ + +error[E0308]: mismatched types + --> $DIR/type-ascription-in-pattern.rs:3:19 + | +LL | fn foo(x: bool) -> i32 { + | --- expected `i32` because of return type +LL | match x { +LL | x: i32 => x, + | ^ expected `i32`, found `bool` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. From c3a71ede7cc459b84ddac53f3435391712fa1f12 Mon Sep 17 00:00:00 2001 From: Aidan Olsen Date: Tue, 31 Jan 2023 16:48:08 -0700 Subject: [PATCH 055/137] Emit warnings on unused parens/braces in index expressions --- compiler/rustc_lint/src/unused.rs | 4 +++ tests/ui/lint/unused/issue-96606.rs | 8 ++++++ tests/ui/lint/unused/issue-96606.stderr | 33 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/ui/lint/unused/issue-96606.rs create mode 100644 tests/ui/lint/unused/issue-96606.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 4c9b3df2dbd3..d829ca43328f 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -495,6 +495,7 @@ enum UnusedDelimsCtx { ArrayLenExpr, AnonConst, MatchArmExpr, + IndexExpr, } impl From for &'static str { @@ -514,6 +515,7 @@ impl From for &'static str { UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression", UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression", UnusedDelimsCtx::MatchArmExpr => "match arm expression", + UnusedDelimsCtx::IndexExpr => "index expression", } } } @@ -733,6 +735,8 @@ trait UnusedDelimLint { (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None) } + Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None), + Assign(_, ref value, _) | AssignOp(.., ref value) => { (value, UnusedDelimsCtx::AssignedValue, false, None, None) } diff --git a/tests/ui/lint/unused/issue-96606.rs b/tests/ui/lint/unused/issue-96606.rs new file mode 100644 index 000000000000..4e7c290fa2a0 --- /dev/null +++ b/tests/ui/lint/unused/issue-96606.rs @@ -0,0 +1,8 @@ +#[deny(unused)] +fn main() { + let arr = [0; 10]; + let _ = arr[(0)]; //~ ERROR unnecessary parentheses around index expression + let _ = arr[{0}]; //~ ERROR unnecessary braces around index expression + let _ = arr[1 + (0)]; + let _ = arr[{ let x = 0; x }]; +} diff --git a/tests/ui/lint/unused/issue-96606.stderr b/tests/ui/lint/unused/issue-96606.stderr new file mode 100644 index 000000000000..e3627718116b --- /dev/null +++ b/tests/ui/lint/unused/issue-96606.stderr @@ -0,0 +1,33 @@ +error: unnecessary parentheses around index expression + --> $DIR/issue-96606.rs:4:17 + | +LL | let _ = arr[(0)]; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-96606.rs:1:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]` +help: remove these parentheses + | +LL - let _ = arr[(0)]; +LL + let _ = arr[0]; + | + +error: unnecessary braces around index expression + --> $DIR/issue-96606.rs:5:17 + | +LL | let _ = arr[{0}]; + | ^ ^ + | + = note: `#[deny(unused_braces)]` implied by `#[deny(unused)]` +help: remove these braces + | +LL - let _ = arr[{0}]; +LL + let _ = arr[0]; + | + +error: aborting due to 2 previous errors + From eb5e9713b5fc4da7cb9dbdc9d302de10126b3287 Mon Sep 17 00:00:00 2001 From: Joseph Ryan Date: Thu, 2 Feb 2023 11:23:48 -0800 Subject: [PATCH 056/137] Use triple rather than arch for fuchsia test runner --- src/ci/docker/scripts/fuchsia-test-runner.py | 51 +++++++++---------- src/doc/rustc/src/platform-support/fuchsia.md | 2 +- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index c8d1ff9aefb7..a6d84a3c18a5 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -19,18 +19,18 @@ import shutil import signal import subprocess import sys -from typing import ClassVar, List +from typing import ClassVar, List, Optional @dataclass class TestEnvironment: rust_dir: str sdk_dir: str - target_arch: str - package_server_pid: int = None - emu_addr: str = None - libstd_name: str = None - libtest_name: str = None + target: str + package_server_pid: Optional[int] = None + emu_addr: Optional[str] = None + libstd_name: Optional[str] = None + libtest_name: Optional[str] = None verbose: bool = False @staticmethod @@ -40,6 +40,15 @@ class TestEnvironment: return os.path.abspath(tmp_dir) return os.path.join(os.path.dirname(__file__), "tmp~") + @staticmethod + def triple_to_arch(triple): + if "x86_64" in triple: + return "x64" + elif "aarch64" in triple: + return "arm64" + else: + raise Exception(f"Unrecognized target triple {triple}") + @classmethod def env_file_path(cls): return os.path.join(cls.tmp_dir(), "test_env.json") @@ -49,7 +58,7 @@ class TestEnvironment: return cls( os.path.abspath(args.rust), os.path.abspath(args.sdk), - args.target_arch, + args.target, verbose=args.verbose, ) @@ -60,7 +69,7 @@ class TestEnvironment: return cls( test_env["rust_dir"], test_env["sdk_dir"], - test_env["target_arch"], + test_env["target"], libstd_name=test_env["libstd_name"], libtest_name=test_env["libtest_name"], emu_addr=test_env["emu_addr"], @@ -68,13 +77,6 @@ class TestEnvironment: verbose=test_env["verbose"], ) - def image_name(self): - if self.target_arch == "x64": - return "qemu-x64" - if self.target_arch == "arm64": - return "qemu-arm64" - raise Exception(f"Unrecognized target architecture {self.target_arch}") - def write_to_file(self): with open(self.env_file_path(), "w", encoding="utf-8") as f: f.write(json.dumps(self.__dict__)) @@ -108,13 +110,6 @@ class TestEnvironment: def repo_dir(self): return os.path.join(self.tmp_dir(), self.TEST_REPO_NAME) - def rustlib_dir(self): - if self.target_arch == "x64": - return "x86_64-unknown-fuchsia" - if self.target_arch == "arm64": - return "aarch64-unknown-fuchsia" - raise Exception(f"Unrecognized target architecture {self.target_arch}") - def libs_dir(self): return os.path.join( self.rust_dir, @@ -125,7 +120,7 @@ class TestEnvironment: return os.path.join( self.libs_dir(), "rustlib", - self.rustlib_dir(), + self.target, "lib", ) @@ -384,7 +379,7 @@ class TestEnvironment: "--emulator-log", self.emulator_log_path(), "--image-name", - self.image_name(), + "qemu-" + self.triple_to_arch(self.target), ], stdout=self.subprocess_output(), stderr=self.subprocess_output(), @@ -642,11 +637,11 @@ class TestEnvironment: package_dir=package_dir, package_name=package_name, rust_dir=self.rust_dir, - rustlib_dir=self.rustlib_dir(), + rustlib_dir=self.target, sdk_dir=self.sdk_dir, libstd_name=self.libstd_name, libtest_name=self.libtest_name, - target_arch=self.target_arch, + target_arch=self.triple_to_arch(self.target), ) ) for shared_lib in shared_libs: @@ -969,8 +964,8 @@ def main(): action="store_true", ) start_parser.add_argument( - "--target-arch", - help="the architecture of the image to test", + "--target", + help="the target platform to test", required=True, ) start_parser.set_defaults(func=start) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 29e70129a62e..0f165b268ba3 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -697,7 +697,7 @@ test environment with: src/ci/docker/scripts/fuchsia-test-runner.py start --rust ${RUST_SRC_PATH}/install --sdk ${SDK_PATH} - --target-arch {x64,arm64} + --target-triple {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} ``` Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and From d8651aae22d3b2251045647e7313fea37381362a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 2 Feb 2023 15:39:00 +0000 Subject: [PATCH 057/137] Don't generate unecessary `&&self.field` in deriving Debug --- .../src/deriving/debug.rs | 25 +++++++++++++++---- tests/ui/deriving/deriving-all-codegen.stdout | 14 +++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 897048f64211..74e2597830e7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -76,6 +76,21 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // The number of fields that can be handled without an array. const CUTOFF: usize = 5; + fn expr_for_field( + cx: &ExtCtxt<'_>, + field: &FieldInfo, + index: usize, + len: usize, + ) -> ast::ptr::P { + if index < len - 1 { + field.self_expr.clone() + } else { + // Unsized types need an extra indirection, but only the last field + // may be unsized. + cx.expr_addr_of(field.span, field.self_expr.clone()) + } + } + if fields.is_empty() { // Special case for no fields. let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); @@ -98,8 +113,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let name = cx.expr_str(field.span, field.name.unwrap().name); args.push(name); } - // Use an extra indirection to make sure this works for unsized types. - let field = cx.expr_addr_of(field.span, field.self_expr.clone()); + + let field = expr_for_field(cx, field, i, fields.len()); args.push(field); } let expr = cx.expr_call_global(span, fn_path_debug, args); @@ -109,13 +124,13 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let mut name_exprs = Vec::with_capacity(fields.len()); let mut value_exprs = Vec::with_capacity(fields.len()); - for field in fields { + for i in 0..fields.len() { + let field = &fields[i]; if is_struct { name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name)); } - // Use an extra indirection to make sure this works for unsized types. - let field = cx.expr_addr_of(field.span, field.self_expr.clone()); + let field = expr_for_field(cx, field, i, fields.len()); value_exprs.push(field); } diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 8e238a509d2f..5bca83e87f87 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -98,7 +98,7 @@ impl ::core::marker::Copy for Point { } impl ::core::fmt::Debug for Point { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", - &&self.x, "y", &&self.y) + &self.x, "y", &&self.y) } } #[automatically_derived] @@ -183,7 +183,7 @@ impl ::core::marker::Copy for PackedPoint { } impl ::core::fmt::Debug for PackedPoint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint", - "x", &&{ self.x }, "y", &&{ self.y }) + "x", &{ self.x }, "y", &&{ self.y }) } } #[automatically_derived] @@ -277,8 +277,8 @@ impl ::core::fmt::Debug for Big { let names: &'static _ = &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; let values: &[&dyn ::core::fmt::Debug] = - &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5, - &&self.b6, &&self.b7, &&self.b8]; + &[&self.b1, &self.b2, &self.b3, &self.b4, &self.b5, &self.b6, + &self.b7, &&self.b8]; ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", names, values) } @@ -565,7 +565,7 @@ impl ::core::fmt::Debug for Generic where T::A: ::core::fmt::Debug { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t", - &&self.t, "ta", &&self.ta, "u", &&self.u) + &self.t, "ta", &self.ta, "u", &&self.u) } } #[automatically_derived] @@ -682,7 +682,7 @@ impl ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric", - &&{ self.0 }, &&{ self.1 }, &&{ self.2 }) + &{ self.0 }, &{ self.1 }, &&{ self.2 }) } } #[automatically_derived] @@ -1084,7 +1084,7 @@ impl ::core::fmt::Debug for Mixed { &__self_0), Mixed::S { d1: __self_0, d2: __self_1 } => ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", - "d1", &__self_0, "d2", &__self_1), + "d1", __self_0, "d2", &__self_1), } } } From 745d60c239d7cf66f1bebca921cf0df0c052ade0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Feb 2023 15:02:21 -0800 Subject: [PATCH 058/137] Tweak misleading comment --- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index cb47522877c2..4ed58e221e61 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -751,7 +751,7 @@ pub trait PrettyPrinter<'tcx>: match self.tcx().def_kind(parent) { DefKind::TyAlias | DefKind::AssocTy => { // NOTE: I know we should check for NO_QUERIES here, but it's alright. - // `type_of` on a TAIT should never cause a cycle. + // `type_of` on a type alias or assoc type should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = *self.tcx().type_of(parent).kind() { From af1d16e82ddc27166438e8bc2a520087862f12af Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 10:53:00 +1100 Subject: [PATCH 059/137] Improve doc comment desugaring. Sometimes the parser needs to desugar a doc comment into `#[doc = r"foo"]`. Currently it does this in a hacky way: by pushing a "fake" new frame (one without a delimiter) onto the `TokenCursor` stack. This commit changes things so that the token stream itself is modified in place. The nice thing about this is that it means `TokenCursorFrame::delim_sp` is now only `None` for the outermost frame. --- compiler/rustc_ast/src/tokenstream.rs | 9 +++++ compiler/rustc_parse/src/parser/mod.rs | 48 +++++++++++--------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index fabd43a1618a..dd01fc8ffc50 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -614,6 +614,15 @@ impl Cursor { pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { self.stream.0.get(self.index + n) } + + // Replace the previously obtained token tree with `tts`, and rewind to + // just before them. + pub fn replace_prev_and_rewind(&mut self, tts: Vec) { + assert!(self.index > 0); + self.index -= 1; + let stream = Lrc::make_mut(&mut self.stream.0); + stream.splice(self.index..self.index + 1, tts); + } } #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ffb23b50a160..0499a56a09db 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -224,7 +224,7 @@ impl<'a> Drop for Parser<'a> { #[derive(Clone)] struct TokenCursor { // The current (innermost) frame. `frame` and `stack` could be combined, - // but it's faster to have them separately to access `frame` directly + // but it's faster to keep them separate and access `frame` directly // rather than via something like `stack.last().unwrap()` or // `stack[stack.len() - 1]`. frame: TokenCursorFrame, @@ -259,6 +259,7 @@ struct TokenCursor { #[derive(Clone)] struct TokenCursorFrame { + // This is `None` only for the outermost frame. delim_sp: Option<(Delimiter, DelimSpan)>, tree_cursor: tokenstream::Cursor, } @@ -285,7 +286,9 @@ impl TokenCursor { match tree { &TokenTree::Token(ref token, spacing) => match (desugar_doc_comments, token) { (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => { - return self.desugar(attr_style, data, span); + let desugared = self.desugar(attr_style, data, span); + self.frame.tree_cursor.replace_prev_and_rewind(desugared); + // Continue to get the first token of the desugared doc comment. } _ => return (token.clone(), spacing), }, @@ -300,19 +303,22 @@ impl TokenCursor { } }; } else if let Some(frame) = self.stack.pop() { - if let Some((delim, span)) = self.frame.delim_sp && delim != Delimiter::Invisible { - self.frame = frame; + // We have exhausted this frame. Move back to its parent frame. + let (delim, span) = self.frame.delim_sp.unwrap(); + self.frame = frame; + if delim != Delimiter::Invisible { return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone); } - self.frame = frame; // No close delimiter to return; continue on to the next iteration. } else { + // We have exhausted the outermost frame. return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone); } } } - fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) { + // Desugar a doc comment into something like `#[doc = r"foo"]`. + fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> Vec { // Searches for the occurrences of `"#*` and returns the minimum number of `#`s // required to wrap the text. E.g. // - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0) @@ -346,27 +352,15 @@ impl TokenCursor { .collect::(), ); - self.stack.push(mem::replace( - &mut self.frame, - TokenCursorFrame::new( - None, - if attr_style == AttrStyle::Inner { - [ - TokenTree::token_alone(token::Pound, span), - TokenTree::token_alone(token::Not, span), - body, - ] - .into_iter() - .collect::() - } else { - [TokenTree::token_alone(token::Pound, span), body] - .into_iter() - .collect::() - }, - ), - )); - - self.next(/* desugar_doc_comments */ false) + if attr_style == AttrStyle::Inner { + vec![ + TokenTree::token_alone(token::Pound, span), + TokenTree::token_alone(token::Not, span), + body, + ] + } else { + vec![TokenTree::token_alone(token::Pound, span), body] + } } } From b23f272db017c3bfd8cdf57fad6e5fdd057168c6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 11:21:28 +1100 Subject: [PATCH 060/137] Make clear that `TokenTree::Token` shouldn't contain a delimiter. --- compiler/rustc_ast/src/tokenstream.rs | 3 ++- compiler/rustc_parse/src/parser/mod.rs | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index dd01fc8ffc50..ab554d70c462 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -41,7 +41,8 @@ use std::{fmt, iter}; /// Nothing special happens to misnamed or misplaced `SubstNt`s. #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum TokenTree { - /// A single token. + /// A single token. Should never be `OpenDelim` or `CloseDelim`, because + /// delimiters are implicitly represented by `Delimited`. Token(Token, Spacing), /// A delimited sequence of token trees. Delimited(DelimSpan, Delimiter, TokenStream), diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0499a56a09db..510588f8a5f7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -290,7 +290,13 @@ impl TokenCursor { self.frame.tree_cursor.replace_prev_and_rewind(desugared); // Continue to get the first token of the desugared doc comment. } - _ => return (token.clone(), spacing), + _ => { + debug_assert!(!matches!( + token.kind, + token::OpenDelim(_) | token::CloseDelim(_) + )); + return (token.clone(), spacing); + } }, &TokenTree::Delimited(sp, delim, ref tts) => { // Set `open_delim` to true here because we deal with it immediately. From b5ecbbb998aae80541d70bf5c93be92e6c59a7a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 12:43:13 +1100 Subject: [PATCH 061/137] Remove `TokenCursorFrame`. The motivation here is to eliminate the `Option<(Delimiter, DelimSpan)>`, which is `None` for the outermost token stream and `Some` for all other token streams. We are already treating the innermost frame specially -- this is the `frame` vs `stack` distinction in `TokenCursor`. We can push that further so that `frame` only contains the cursor, and `stack` elements contain the delimiters for their children. When we are in the outermost token stream `stack` is empty, so there are no stored delimiters, which is what we want because the outermost token stream *has* no delimiters. This change also shrinks `TokenCursor`, which shrinks `Parser` and `LazyAttrTokenStreamImpl`, which is nice. --- .../rustc_parse/src/parser/attr_wrapper.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 72 +++++++++---------- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index b97f22417cb7..dbd3b76786f4 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -469,6 +469,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(AttrWrapper, 16); - static_assert_size!(LazyAttrTokenStreamImpl, 144); + static_assert_size!(LazyAttrTokenStreamImpl, 120); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b7a023868fce..68849f817aa5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2141,7 +2141,7 @@ impl<'a> Parser<'a> { } if self.token.kind == TokenKind::Semi - && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _))) + && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _))) && self.may_recover() { // It is likely that the closure body is a block but where the diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 510588f8a5f7..982fde727c89 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -168,7 +168,7 @@ pub struct Parser<'a> { // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 336); +rustc_data_structures::static_assert_size!(Parser<'_>, 312); /// Stores span information about a closure. #[derive(Clone)] @@ -223,16 +223,21 @@ impl<'a> Drop for Parser<'a> { #[derive(Clone)] struct TokenCursor { - // The current (innermost) frame. `frame` and `stack` could be combined, - // but it's faster to keep them separate and access `frame` directly - // rather than via something like `stack.last().unwrap()` or - // `stack[stack.len() - 1]`. - frame: TokenCursorFrame, - // Additional frames that enclose `frame`. - stack: Vec, + // Cursor for the current (innermost) token stream. The delimiters for this + // token stream are found in `self.stack.last()`; when that is `None` then + // we are in the outermost token stream which never has delimiters. + tree_cursor: tokenstream::Cursor, + + // Token streams surrounding the current one. The delimiters for stack[n]'s + // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters + // because it's the outermost token stream which never has delimiters. + stack: Vec<(tokenstream::Cursor, Delimiter, DelimSpan)>, + desugar_doc_comments: bool, + // Counts the number of calls to `{,inlined_}next`. num_next_calls: usize, + // During parsing, we may sometimes need to 'unglue' a // glued token into two component tokens // (e.g. '>>' into '>' and '>), so that the parser @@ -257,19 +262,6 @@ struct TokenCursor { break_last_token: bool, } -#[derive(Clone)] -struct TokenCursorFrame { - // This is `None` only for the outermost frame. - delim_sp: Option<(Delimiter, DelimSpan)>, - tree_cursor: tokenstream::Cursor, -} - -impl TokenCursorFrame { - fn new(delim_sp: Option<(Delimiter, DelimSpan)>, tts: TokenStream) -> Self { - TokenCursorFrame { delim_sp, tree_cursor: tts.into_trees() } - } -} - impl TokenCursor { fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) { self.inlined_next(desugar_doc_comments) @@ -282,12 +274,12 @@ impl TokenCursor { // FIXME: we currently don't return `Delimiter` open/close delims. To fix #67062 we will // need to, whereupon the `delim != Delimiter::Invisible` conditions below can be // removed. - if let Some(tree) = self.frame.tree_cursor.next_ref() { + if let Some(tree) = self.tree_cursor.next_ref() { match tree { &TokenTree::Token(ref token, spacing) => match (desugar_doc_comments, token) { (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => { let desugared = self.desugar(attr_style, data, span); - self.frame.tree_cursor.replace_prev_and_rewind(desugared); + self.tree_cursor.replace_prev_and_rewind(desugared); // Continue to get the first token of the desugared doc comment. } _ => { @@ -299,25 +291,23 @@ impl TokenCursor { } }, &TokenTree::Delimited(sp, delim, ref tts) => { - // Set `open_delim` to true here because we deal with it immediately. - let frame = TokenCursorFrame::new(Some((delim, sp)), tts.clone()); - self.stack.push(mem::replace(&mut self.frame, frame)); + let trees = tts.clone().into_trees(); + self.stack.push((mem::replace(&mut self.tree_cursor, trees), delim, sp)); if delim != Delimiter::Invisible { return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone); } // No open delimiter to return; continue on to the next iteration. } }; - } else if let Some(frame) = self.stack.pop() { - // We have exhausted this frame. Move back to its parent frame. - let (delim, span) = self.frame.delim_sp.unwrap(); - self.frame = frame; + } else if let Some((tree_cursor, delim, span)) = self.stack.pop() { + // We have exhausted this token stream. Move back to its parent token stream. + self.tree_cursor = tree_cursor; if delim != Delimiter::Invisible { return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone); } // No close delimiter to return; continue on to the next iteration. } else { - // We have exhausted the outermost frame. + // We have exhausted the outermost token stream. return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone); } } @@ -475,7 +465,7 @@ impl<'a> Parser<'a> { restrictions: Restrictions::empty(), expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(None, tokens), + tree_cursor: tokens.into_trees(), stack: Vec::new(), num_next_calls: 0, desugar_doc_comments, @@ -1142,14 +1132,16 @@ impl<'a> Parser<'a> { return looker(&self.token); } - let frame = &self.token_cursor.frame; - if let Some((delim, span)) = frame.delim_sp && delim != Delimiter::Invisible { + let tree_cursor = &self.token_cursor.tree_cursor; + if let Some(&(_, delim, span)) = self.token_cursor.stack.last() + && delim != Delimiter::Invisible + { let all_normal = (0..dist).all(|i| { - let token = frame.tree_cursor.look_ahead(i); + let token = tree_cursor.look_ahead(i); !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _))) }); if all_normal { - return match frame.tree_cursor.look_ahead(dist - 1) { + return match tree_cursor.look_ahead(dist - 1) { Some(tree) => match tree { TokenTree::Token(token, _) => looker(token), TokenTree::Delimited(dspan, delim, _) => { @@ -1310,10 +1302,10 @@ impl<'a> Parser<'a> { pub(crate) fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { - // Grab the tokens from this frame. - let frame = &self.token_cursor.frame; - let stream = frame.tree_cursor.stream.clone(); - let (delim, span) = frame.delim_sp.unwrap(); + // Grab the tokens within the delimiters. + let tree_cursor = &self.token_cursor.tree_cursor; + let stream = tree_cursor.stream.clone(); + let (_, delim, span) = *self.token_cursor.stack.last().unwrap(); // Advance the token cursor through the entire delimited // sequence. After getting the `OpenDelim` we are *within* the From a86fc727fa9b9fa1ac60b67147736783b3376e91 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Feb 2023 12:58:04 +1100 Subject: [PATCH 062/137] Rename `Cursor`/`CursorRef` as `TokenTreeCursor`/`RefTokenTreeCursor`. This makes it clear they return token trees, and makes for a nice comparison against `TokenCursor` which returns tokens. --- compiler/rustc_ast/src/tokenstream.rs | 30 ++++++++++--------- compiler/rustc_expand/src/mbe/metavar_expr.rs | 12 ++++---- compiler/rustc_parse/src/parser/mod.rs | 13 ++++---- src/tools/rustfmt/src/macros.rs | 8 ++--- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index ab554d70c462..f0a6a5e07258 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -389,12 +389,12 @@ impl TokenStream { self.0.len() } - pub fn trees(&self) -> CursorRef<'_> { - CursorRef::new(self) + pub fn trees(&self) -> RefTokenTreeCursor<'_> { + RefTokenTreeCursor::new(self) } - pub fn into_trees(self) -> Cursor { - Cursor::new(self) + pub fn into_trees(self) -> TokenTreeCursor { + TokenTreeCursor::new(self) } /// Compares two `TokenStream`s, checking equality without regarding span information. @@ -552,16 +552,17 @@ impl TokenStream { } } -/// By-reference iterator over a [`TokenStream`]. +/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree` +/// items. #[derive(Clone)] -pub struct CursorRef<'t> { +pub struct RefTokenTreeCursor<'t> { stream: &'t TokenStream, index: usize, } -impl<'t> CursorRef<'t> { +impl<'t> RefTokenTreeCursor<'t> { fn new(stream: &'t TokenStream) -> Self { - CursorRef { stream, index: 0 } + RefTokenTreeCursor { stream, index: 0 } } pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> { @@ -569,7 +570,7 @@ impl<'t> CursorRef<'t> { } } -impl<'t> Iterator for CursorRef<'t> { +impl<'t> Iterator for RefTokenTreeCursor<'t> { type Item = &'t TokenTree; fn next(&mut self) -> Option<&'t TokenTree> { @@ -580,15 +581,16 @@ impl<'t> Iterator for CursorRef<'t> { } } -/// Owning by-value iterator over a [`TokenStream`]. +/// Owning by-value iterator over a [`TokenStream`], that produces `TokenTree` +/// items. // FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones. #[derive(Clone)] -pub struct Cursor { +pub struct TokenTreeCursor { pub stream: TokenStream, index: usize, } -impl Iterator for Cursor { +impl Iterator for TokenTreeCursor { type Item = TokenTree; fn next(&mut self) -> Option { @@ -599,9 +601,9 @@ impl Iterator for Cursor { } } -impl Cursor { +impl TokenTreeCursor { fn new(stream: TokenStream) -> Self { - Cursor { stream, index: 0 } + TokenTreeCursor { stream, index: 0 } } #[inline] diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 99fe474541e9..de34df0114a7 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -1,5 +1,5 @@ use rustc_ast::token::{self, Delimiter}; -use rustc_ast::tokenstream::{CursorRef, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; use rustc_ast::{LitIntType, LitKind}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; @@ -72,7 +72,7 @@ impl MetaVarExpr { // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` fn check_trailing_token<'sess>( - iter: &mut CursorRef<'_>, + iter: &mut RefTokenTreeCursor<'_>, sess: &'sess ParseSess, ) -> PResult<'sess, ()> { if let Some(tt) = iter.next() { @@ -88,7 +88,7 @@ fn check_trailing_token<'sess>( /// Parse a meta-variable `count` expression: `count(ident[, depth])` fn parse_count<'sess>( - iter: &mut CursorRef<'_>, + iter: &mut RefTokenTreeCursor<'_>, sess: &'sess ParseSess, span: Span, ) -> PResult<'sess, MetaVarExpr> { @@ -99,7 +99,7 @@ fn parse_count<'sess>( /// Parses the depth used by index(depth) and length(depth). fn parse_depth<'sess>( - iter: &mut CursorRef<'_>, + iter: &mut RefTokenTreeCursor<'_>, sess: &'sess ParseSess, span: Span, ) -> PResult<'sess, usize> { @@ -126,7 +126,7 @@ fn parse_depth<'sess>( /// Parses an generic ident fn parse_ident<'sess>( - iter: &mut CursorRef<'_>, + iter: &mut RefTokenTreeCursor<'_>, sess: &'sess ParseSess, span: Span, ) -> PResult<'sess, Ident> { @@ -152,7 +152,7 @@ fn parse_ident<'sess>( /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the /// iterator is not modified and the result is `false`. -fn try_eat_comma(iter: &mut CursorRef<'_>) -> bool { +fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) { let _ = iter.next(); return true; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 982fde727c89..2ea55f838a37 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -19,9 +19,8 @@ pub use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind}; -use rustc_ast::tokenstream::AttributesData; -use rustc_ast::tokenstream::{self, DelimSpan, Spacing}; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::tokenstream::{AttributesData, DelimSpan, Spacing}; +use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::util::case::Case; use rustc_ast::AttrId; use rustc_ast::DUMMY_NODE_ID; @@ -221,17 +220,21 @@ impl<'a> Drop for Parser<'a> { } } +/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that +/// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b) +/// use this type to emit them as a linear sequence. But a linear sequence is +/// what the parser expects, for the most part. #[derive(Clone)] struct TokenCursor { // Cursor for the current (innermost) token stream. The delimiters for this // token stream are found in `self.stack.last()`; when that is `None` then // we are in the outermost token stream which never has delimiters. - tree_cursor: tokenstream::Cursor, + tree_cursor: TokenTreeCursor, // Token streams surrounding the current one. The delimiters for stack[n]'s // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters // because it's the outermost token stream which never has delimiters. - stack: Vec<(tokenstream::Cursor, Delimiter, DelimSpan)>, + stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>, desugar_doc_comments: bool, diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index d58f7547fefb..7978d8cba954 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ @@ -736,7 +736,7 @@ impl MacroArgParser { self.buf.clear(); } - fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { + fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> { match iter.next() { Some(TokenTree::Token( Token { @@ -768,7 +768,7 @@ impl MacroArgParser { &mut self, inner: Vec, delim: Delimiter, - iter: &mut Cursor, + iter: &mut TokenTreeCursor, ) -> Option<()> { let mut buffer = String::new(); let mut first = true; @@ -1121,7 +1121,7 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D // Currently we do not attempt to parse any further than that. #[derive(new)] struct MacroParser { - toks: Cursor, + toks: TokenTreeCursor, } impl MacroParser { From 0241c29123c7a49b5fdcc99e32b605124abe4e09 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 23 Jan 2023 22:15:33 +0000 Subject: [PATCH 063/137] Put a DefId in AggregateKind. --- .../src/diagnostics/conflict_errors.rs | 3 ++- .../rustc_borrowck/src/diagnostics/mod.rs | 2 ++ compiler/rustc_borrowck/src/lib.rs | 1 + compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- .../src/transform/check_consts/check.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 21 +++++++++++++------ compiler/rustc_middle/src/mir/syntax.rs | 6 ++---- compiler/rustc_middle/src/mir/tcx.rs | 4 ++-- .../src/build/expr/as_rvalue.rs | 8 +++++-- .../rustc_mir_transform/src/check_unsafety.rs | 1 + 10 files changed, 33 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 50c0faf4597f..b0a8188e5e04 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2645,6 +2645,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { operands, ) = rvalue { + let def_id = def_id.expect_local(); for operand in operands { let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { continue; @@ -2667,7 +2668,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // into a place then we should annotate the closure in // case it ends up being assigned into the return place. annotated_closure = - self.annotate_fn_sig(*def_id, substs.as_closure().sig()); + self.annotate_fn_sig(def_id, substs.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 8c579bac7e8e..a75ec87be4ca 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -817,6 +817,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind { debug!("move_spans: def_id={:?} places={:?}", def_id, places); + let def_id = def_id.expect_local(); if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(def_id, moved_place, places) { @@ -945,6 +946,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { box AggregateKind::Generator(def_id, _, _) => (def_id, true), _ => continue, }; + let def_id = def_id.expect_local(); debug!( "borrow_spans: def_id={:?} is_generator={:?} places={:?}", diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index bc81abe4005c..98103af779d8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1278,6 +1278,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // in order to populate our used_mut set. match **aggregate_kind { AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { + let def_id = def_id.expect_local(); let BorrowCheckResult { used_mut_upvars, .. } = self.infcx.tcx.mir_borrowck(def_id); debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6c67e1a00c35..5b52846562f8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2536,7 +2536,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // clauses on the struct. AggregateKind::Closure(def_id, substs) | AggregateKind::Generator(def_id, substs, _) => { - (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location)) + (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)) } AggregateKind::Array(_) | AggregateKind::Tuple => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index f47e3e86ebe2..1a23b06d2e89 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -453,7 +453,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Aggregate(kind, ..) => { if let AggregateKind::Generator(def_id, ..) = kind.as_ref() - && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id.to_def_id()) + && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id) { self.check_op(ops::Generator(generator_kind)); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 05a9ec5e6d04..10ac7e0d39af 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2098,10 +2098,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { let substs = tcx.lift(substs).unwrap(); - format!( - "[closure@{}]", - tcx.def_path_str_with_substs(def_id.to_def_id(), substs), - ) + format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),) } else { let span = tcx.def_span(def_id); format!( @@ -2112,11 +2109,17 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); // FIXME(project-rfc-2229#48): This should be a list of capture names/places - if let Some(upvars) = tcx.upvars_mentioned(def_id) { + if let Some(def_id) = def_id.as_local() + && let Some(upvars) = tcx.upvars_mentioned(def_id) + { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(var_name.as_str(), place); } + } else { + for (index, place) in places.iter().enumerate() { + struct_fmt.field(&format!("{index}"), place); + } } struct_fmt.finish() @@ -2127,11 +2130,17 @@ impl<'tcx> Debug for Rvalue<'tcx> { let mut struct_fmt = fmt.debug_struct(&name); // FIXME(project-rfc-2229#48): This should be a list of capture names/places - if let Some(upvars) = tcx.upvars_mentioned(def_id) { + if let Some(def_id) = def_id.as_local() + && let Some(upvars) = tcx.upvars_mentioned(def_id) + { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); struct_fmt.field(var_name.as_str(), place); } + } else { + for (index, place) in places.iter().enumerate() { + struct_fmt.field(&format!("{index}"), place); + } } struct_fmt.finish() diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 549bc65d6d79..66ee68187896 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1203,10 +1203,8 @@ pub enum AggregateKind<'tcx> { /// active field index would identity the field `c` Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option, Option), - // Note: We can use LocalDefId since closures and generators a deaggregated - // before codegen. - Closure(LocalDefId, SubstsRef<'tcx>), - Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability), + Closure(DefId, SubstsRef<'tcx>), + Generator(DefId, SubstsRef<'tcx>, hir::Movability), } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 599f0b9d3fab..b5e0b88bbe52 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -205,9 +205,9 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Adt(did, _, substs, _, _) => { tcx.bound_type_of(did).subst(tcx, substs) } - AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs), + AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), AggregateKind::Generator(did, substs, movability) => { - tcx.mk_generator(did.to_def_id(), substs, movability) + tcx.mk_generator(did, substs, movability) } }, Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index c7b3eb44dc5f..cd0e69328634 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -439,10 +439,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We implicitly set the discriminant to 0. See // librustc_mir/transform/deaggregator.rs for details. let movability = movability.unwrap(); - Box::new(AggregateKind::Generator(closure_id, substs, movability)) + Box::new(AggregateKind::Generator( + closure_id.to_def_id(), + substs, + movability, + )) } UpvarSubsts::Closure(substs) => { - Box::new(AggregateKind::Closure(closure_id, substs)) + Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs)) } }; block.and(Rvalue::Aggregate(result, operands)) diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 8afa53313fc2..d00ee1f4babe 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -126,6 +126,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { } } &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { + let def_id = def_id.expect_local(); let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.unsafety_check_result(def_id); self.register_violations(violations, used_unsafe_blocks.iter().copied()); From feccf469fbeb96c97d3b6a5f3186867afe0571f5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 23 Jan 2023 22:15:55 +0000 Subject: [PATCH 064/137] Interpret aggregates. --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 5 +++++ .../rustc_const_eval/src/interpret/place.rs | 9 --------- .../rustc_const_eval/src/interpret/step.rs | 20 +++++++++++++++---- ..._allocation.main.ConstProp.after.64bit.mir | 16 +++++++-------- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 23196c8cbaea..b49e241bec0b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_target::abi::VariantIdx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { #[instrument(level = "trace", skip(self, bx))] @@ -115,6 +116,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (dest, active_field_index) } } + mir::AggregateKind::Generator(..) => { + dest.codegen_set_discr(bx, VariantIdx::from_u32(0)); + (dest, None) + } _ => (dest, None), }; for (i, operand) in operands.iter().enumerate() { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 274af61ee7c1..5c00dc21d04e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -774,15 +774,6 @@ where variant_index: VariantIdx, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - // This must be an enum or generator. - match dest.layout.ty.kind() { - ty::Adt(adt, _) => assert!(adt.is_enum()), - ty::Generator(..) => {} - _ => span_bug!( - self.cur_span(), - "write_discriminant called on non-variant-type (neither enum nor generator)" - ), - } // Layout computation excludes uninhabited variants from consideration // therefore there's no way to represent those variants in the given layout. // Essentially, uninhabited variants do not have a tag that corresponds to their diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d101937fd740..7e00d90342e1 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -7,6 +7,7 @@ use either::Either; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; +use rustc_target::abi::VariantIdx; use super::{ImmTy, InterpCx, Machine}; @@ -199,13 +200,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Aggregate(box ref kind, ref operands) => { - assert!(matches!(kind, mir::AggregateKind::Array(..))); - + self.write_uninit(&dest)?; + let (variant_index, variant_dest, active_field_index) = match *kind { + mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { + let variant_dest = self.place_downcast(&dest, variant_index)?; + (variant_index, variant_dest, active_field_index) + } + _ => (VariantIdx::from_u32(0), dest.clone(), None), + }; + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } for (field_index, operand) in operands.iter().enumerate() { - let op = self.eval_operand(operand, None)?; - let field_dest = self.place_field(&dest, field_index)?; + let field_index = active_field_index.unwrap_or(field_index); + let field_dest = self.place_field(&variant_dest, field_index)?; + let op = self.eval_operand(operand, Some(field_dest.layout))?; self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; } + self.write_discriminant(variant_index, &dest)?; } Repeat(ref operand, _) => { diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index b2ed23c6873c..d0f196e72458 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -27,19 +27,19 @@ alloc1 (static: FOO, size: 16, align: 8) { alloc18 (size: 72, align: 8) { 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............â–‘â–‘â–‘â–‘ - 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } alloc5 (size: 0, align: 8) {} -alloc9 (size: 32, align: 8) { - 0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc8 (size: 32, align: 8) { + 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ 0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc8 (size: 3, align: 1) { +alloc9 (size: 3, align: 1) { 66 6f 6f │ foo } @@ -47,13 +47,13 @@ alloc10 (size: 3, align: 1) { 62 61 72 │ bar } -alloc14 (size: 48, align: 8) { - 0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc13 (size: 48, align: 8) { + 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ 0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ 0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc13 (size: 3, align: 1) { +alloc14 (size: 3, align: 1) { 6d 65 68 │ meh } From 20dd5e09fdeec25a7a6206e95ea8706e20ab8a01 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 29 Jan 2023 13:00:32 +0000 Subject: [PATCH 065/137] Codegen SetDiscriminant after field assignment. This matches the order in which deaggregation was performed. --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 26 +++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index b49e241bec0b..35948e50f48d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -107,21 +107,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Aggregate(ref kind, ref operands) => { - let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { - dest.codegen_set_discr(bx, variant_index); - if bx.tcx().adt_def(adt_did).is_enum() { - (dest.project_downcast(bx, variant_index), active_field_index) - } else { - (dest, active_field_index) - } + let (variant_index, variant_dest, active_field_index) = match **kind { + mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { + let variant_dest = dest.project_downcast(bx, variant_index); + (variant_index, variant_dest, active_field_index) } - mir::AggregateKind::Generator(..) => { - dest.codegen_set_discr(bx, VariantIdx::from_u32(0)); - (dest, None) - } - _ => (dest, None), + _ => (VariantIdx::from_u32(0), dest, None), }; + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } for (i, operand) in operands.iter().enumerate() { let op = self.codegen_operand(bx, operand); // Do not generate stores and GEPis for zero-sized fields. @@ -129,13 +124,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let field_index = active_field_index.unwrap_or(i); let field = if let mir::AggregateKind::Array(_) = **kind { let llindex = bx.cx().const_usize(field_index as u64); - dest.project_index(bx, llindex) + variant_dest.project_index(bx, llindex) } else { - dest.project_field(bx, field_index) + variant_dest.project_field(bx, field_index) }; op.val.store(bx, field); } } + dest.codegen_set_discr(bx, variant_index); } _ => { From b62a9da0c839fa3e722d4baf3e50ce58b749bc8e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 24 Jan 2023 17:43:07 +0000 Subject: [PATCH 066/137] Handle aggregates in DataflowConstProp. --- .../src/dataflow_const_prop.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index c75fe2327de3..949a59a97bfb 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -5,6 +5,7 @@ use rustc_const_eval::const_eval::CheckAlignment; use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar}; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::DefKind; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -85,6 +86,30 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { state: &mut State, ) { match rvalue { + Rvalue::Aggregate(kind, operands) => { + let target = self.map().find(target.as_ref()); + if let Some(target) = target { + state.flood_idx_with(target, self.map(), FlatSet::Bottom); + let field_based = match **kind { + AggregateKind::Tuple | AggregateKind::Closure(..) => true, + AggregateKind::Adt(def_id, ..) => { + matches!(self.tcx.def_kind(def_id), DefKind::Struct) + } + _ => false, + }; + if field_based { + for (field_index, operand) in operands.iter().enumerate() { + if let Some(field) = self + .map() + .apply(target, TrackElem::Field(Field::from_usize(field_index))) + { + let result = self.handle_operand(operand, state); + state.assign_idx(field, result, self.map()); + } + } + } + } + } Rvalue::CheckedBinaryOp(op, box (left, right)) => { let target = self.map().find(target.as_ref()); if let Some(target) = target { From 6a0b218161ddeeeb4adac8caa8c0e6bae32a4bed Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 25 Jan 2023 18:34:19 +0000 Subject: [PATCH 067/137] Stop deaggregating enums in MIR. --- .../src/transform/validate.rs | 22 ++----- .../rustc_mir_transform/src/deaggregator.rs | 24 ++++---- compiler/rustc_mir_transform/src/generator.rs | 30 ++++------ compiler/rustc_mir_transform/src/shim.rs | 25 ++++---- ...await.a-{closure#0}.generator_resume.0.mir | 4 +- ...await.b-{closure#0}.generator_resume.0.mir | 10 +--- .../const_debuginfo.main.ConstDebugInfo.diff | 4 +- .../discriminant.main.ConstProp.32bit.diff | 11 ++-- .../discriminant.main.ConstProp.64bit.diff | 11 ++-- ...es_into_variable.main.ConstProp.32bit.diff | 7 +-- ...n.ScalarReplacementOfAggregates.32bit.diff | 21 ++----- .../enum.main.DataflowConstProp.diff | 4 +- ...aggregator_test_enum.bar.Deaggregator.diff | 20 ------- tests/mir-opt/deaggregator_test_enum.rs | 19 ------ tests/mir-opt/deaggregator_test_enum_2.rs | 21 ------- ...egator_test_enum_2.test1.Deaggregator.diff | 45 -------------- tests/mir-opt/deaggregator_test_multiple.rs | 17 ------ ...gator_test_multiple.test.Deaggregator.diff | 35 ----------- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 24 ++------ ...float_to_exponential_common.ConstProp.diff | 14 +++-- ...ny.main-{closure#0}.generator_resume.0.mir | 4 +- .../inline/inline_generator.main.Inline.diff | 8 +-- ...e_75439.foo.MatchBranchSimplification.diff | 7 +-- ...asts.SimplifyCfg-elaborate-drops.after.mir | 6 +- ...t_switch.identity.SeparateConstSwitch.diff | 60 ++++++------------- ...witch.too_complex.SeparateConstSwitch.diff | 50 ++++++---------- ..._option_map_e2e.ezmap.PreCodegen.after.mir | 7 +-- ...s.d1.SimplifyLocals-before-const-prop.diff | 3 +- ...s.d2.SimplifyLocals-before-const-prop.diff | 6 +- ...s_fixedpoint.foo.SimplifyLocals-final.diff | 6 +- ....map.SimplifyLocals-before-const-prop.diff | 7 +-- ...a.enums.ScalarReplacementOfAggregates.diff | 4 +- ...oa.flat.ScalarReplacementOfAggregates.diff | 4 +- .../try_identity_e2e.new.PreCodegen.after.mir | 33 +++++----- .../try_identity_e2e.old.PreCodegen.after.mir | 8 +-- ...after-uninhabited-enum-branching.after.mir | 6 +- ...anching.main.UninhabitedEnumBranching.diff | 6 +- ...after-uninhabited-enum-branching.after.mir | 3 +- ...nching2.main.UninhabitedEnumBranching.diff | 3 +- ...pes.Test-X-{constructor#0}.built.after.mir | 4 +- ..._let_loops.change_loop_body.ConstProp.diff | 3 +- 41 files changed, 166 insertions(+), 440 deletions(-) delete mode 100644 tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff delete mode 100644 tests/mir-opt/deaggregator_test_enum.rs delete mode 100644 tests/mir-opt/deaggregator_test_enum_2.rs delete mode 100644 tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff delete mode 100644 tests/mir-opt/deaggregator_test_multiple.rs delete mode 100644 tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 72f456138ef5..76b316cdf0c3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -8,10 +8,10 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, - Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, - ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, - Terminator, TerminatorKind, UnOp, START_BLOCK, + traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, + MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, + RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, + TerminatorKind, UnOp, START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -423,19 +423,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; } match rvalue { - Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {} - Rvalue::Aggregate(agg_kind, _) => { - let disallowed = match **agg_kind { - AggregateKind::Array(..) => false, - _ => self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup), - }; - if disallowed { - self.fail( - location, - format!("{:?} have been lowered to field assignments", rvalue), - ) - } - } + Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {} Rvalue::Ref(_, BorrowKind::Shallow, _) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs index fe272de20f8d..905e127b7cb8 100644 --- a/compiler/rustc_mir_transform/src/deaggregator.rs +++ b/compiler/rustc_mir_transform/src/deaggregator.rs @@ -1,5 +1,6 @@ use crate::util::expand_aggregate; use crate::MirPass; +use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -11,16 +12,19 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { for bb in basic_blocks { bb.expand_statements(|stmt| { // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL). - match stmt.kind { - // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. - StatementKind::Assign(box ( - _, - Rvalue::Aggregate(box AggregateKind::Array(_), _), - )) => { - return None; - } - StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {} - _ => return None, + let StatementKind::Assign(box ( + _, Rvalue::Aggregate(box ref kind, _)) + ) = stmt.kind else { return None }; + + // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. + if let AggregateKind::Array(_) = kind { + return None; + } + + if let AggregateKind::Adt(def_id, ..) = kind + && matches!(tcx.def_kind(def_id), DefKind::Enum) + { + return None; } let stmt = stmt.replace_nop(); diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 5624e312da1c..47f9d35a4f7e 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -52,7 +52,6 @@ use crate::deref_separator::deref_finder; use crate::simplify; -use crate::util::expand_aggregate; use crate::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::pluralize; @@ -272,31 +271,26 @@ impl<'tcx> TransformVisitor<'tcx> { assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0); // FIXME(swatinem): assert that `val` is indeed unit? - statements.extend(expand_aggregate( - Place::return_place(), - std::iter::empty(), - kind, + statements.push(Statement { + kind: StatementKind::Assign(Box::new(( + Place::return_place(), + Rvalue::Aggregate(Box::new(kind), vec![]), + ))), source_info, - self.tcx, - )); + }); return; } // else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)` assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1); - let ty = self - .tcx - .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did) - .subst(self.tcx, self.state_substs); - - statements.extend(expand_aggregate( - Place::return_place(), - std::iter::once((val, ty)), - kind, + statements.push(Statement { + kind: StatementKind::Assign(Box::new(( + Place::return_place(), + Rvalue::Aggregate(Box::new(kind), vec![val]), + ))), source_info, - self.tcx, - )); + }); } // Create a Place referencing a generator struct field diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e9ca6f7c93c4..551422386f6e 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -15,7 +15,6 @@ use rustc_target::spec::abi::Abi; use std::fmt; use std::iter; -use crate::util::expand_aggregate; use crate::{ abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, pass_manager as pm, remove_noop_landing_pads, simplify, @@ -831,19 +830,23 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { // return; debug!("build_ctor: variant_index={:?}", variant_index); - let statements = expand_aggregate( - Place::return_place(), - adt_def.variant(variant_index).fields.iter().enumerate().map(|(idx, field_def)| { - (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs)) - }), - AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None), + let kind = AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None); + let variant = adt_def.variant(variant_index); + let statement = Statement { + kind: StatementKind::Assign(Box::new(( + Place::return_place(), + Rvalue::Aggregate( + Box::new(kind), + (0..variant.fields.len()) + .map(|idx| Operand::Move(Place::from(Local::new(idx + 1)))) + .collect(), + ), + ))), source_info, - tcx, - ) - .collect(); + }; let start_block = BasicBlockData { - statements, + statements: vec![statement], terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), is_cleanup: false, }; diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir index 2a7f90fe9476..accb504c088e 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir @@ -24,9 +24,7 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]> bb1: { _4 = move _2; // scope 0 at $DIR/async_await.rs:+0:14: +0:16 _3 = const (); // scope 0 at $DIR/async_await.rs:+0:14: +0:16 - Deinit(_0); // scope 0 at $DIR/async_await.rs:+0:16: +0:16 - ((_0 as Ready).0: ()) = move _3; // scope 0 at $DIR/async_await.rs:+0:16: +0:16 - discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+0:16: +0:16 + _0 = Poll::<()>::Ready(move _3); // scope 0 at $DIR/async_await.rs:+0:16: +0:16 discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; // scope 0 at $DIR/async_await.rs:+0:16: +0:16 return; // scope 0 at $DIR/async_await.rs:+0:16: +0:16 } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index 1449247aedad..ad4e5c6fcfd7 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -167,8 +167,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_19); // scope 1 at $DIR/async_await.rs:+1:8: +1:14 StorageLive(_20); // scope 1 at $DIR/async_await.rs:+1:8: +1:14 _20 = (); // scope 1 at $DIR/async_await.rs:+1:8: +1:14 - Deinit(_0); // scope 1 at $DIR/async_await.rs:+1:8: +1:14 - discriminant(_0) = 1; // scope 1 at $DIR/async_await.rs:+1:8: +1:14 + _0 = Poll::<()>::Pending; // scope 1 at $DIR/async_await.rs:+1:8: +1:14 discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; // scope 1 at $DIR/async_await.rs:+1:8: +1:14 return; // scope 1 at $DIR/async_await.rs:+1:8: +1:14 } @@ -276,8 +275,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_35); // scope 4 at $DIR/async_await.rs:+2:8: +2:14 StorageLive(_36); // scope 4 at $DIR/async_await.rs:+2:8: +2:14 _36 = (); // scope 4 at $DIR/async_await.rs:+2:8: +2:14 - Deinit(_0); // scope 4 at $DIR/async_await.rs:+2:8: +2:14 - discriminant(_0) = 1; // scope 4 at $DIR/async_await.rs:+2:8: +2:14 + _0 = Poll::<()>::Pending; // scope 4 at $DIR/async_await.rs:+2:8: +2:14 discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; // scope 4 at $DIR/async_await.rs:+2:8: +2:14 return; // scope 4 at $DIR/async_await.rs:+2:8: +2:14 } @@ -317,9 +315,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, } bb26: { - Deinit(_0); // scope 0 at $DIR/async_await.rs:+3:2: +3:2 - ((_0 as Ready).0: ()) = move _37; // scope 0 at $DIR/async_await.rs:+3:2: +3:2 - discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+3:2: +3:2 + _0 = Poll::<()>::Ready(move _37); // scope 0 at $DIR/async_await.rs:+3:2: +3:2 discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; // scope 0 at $DIR/async_await.rs:+3:2: +3:2 return; // scope 0 at $DIR/async_await.rs:+3:2: +3:2 } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 4405b55875ed..f4e9d53286f5 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -79,9 +79,7 @@ _15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 _16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 - Deinit(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - discriminant(_10) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + _10 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff index b4dccecc6726..b9a10704be0d 100644 --- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff @@ -17,17 +17,20 @@ StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 +- _3 = Option::::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ _3 = const Option::::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 ++ // mir::Constant ++ // + span: $DIR/discriminant.rs:12:34: 12:44 ++ // + literal: Const { ty: Option, val: Value(Scalar(0x01)) } + _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb1: { - switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 +- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb2: { diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff index b4dccecc6726..b9a10704be0d 100644 --- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff @@ -17,17 +17,20 @@ StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 +- _3 = Option::::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ _3 = const Option::::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 ++ // mir::Constant ++ // + span: $DIR/discriminant.rs:12:34: 12:44 ++ // + literal: Const { ty: Option, val: Value(Scalar(0x01)) } + _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb1: { - switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 +- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb2: { diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index 7c7aeac4c451..1368b114658d 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -52,9 +52,8 @@ StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff index 3f9f3b2eac71..de1d57ed401a 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff @@ -10,8 +10,6 @@ let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -47,21 +45,10 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 -- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 -+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 -+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff index fce18fae4362..d049c79d78de 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff @@ -23,9 +23,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21 - ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21 - discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21 + _1 = E::V1(const 0_i32); // scope 0 at $DIR/enum.rs:+1:13: +1:21 StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10 _3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20 switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20 diff --git a/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff b/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff deleted file mode 100644 index f28c2b482af2..000000000000 --- a/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff +++ /dev/null @@ -1,20 +0,0 @@ -- // MIR for `bar` before Deaggregator -+ // MIR for `bar` after Deaggregator - - fn bar(_1: usize) -> Baz { - debug a => _1; // in scope 0 at $DIR/deaggregator_test_enum.rs:+0:8: +0:9 - let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test_enum.rs:+0:21: +0:24 - let mut _2: usize; // in scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20 - _2 = _1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20 -- _0 = Baz::Foo { x: move _2 }; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22 -+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22 -+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22 -+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22 - StorageDead(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:21: +1:22 - return; // scope 0 at $DIR/deaggregator_test_enum.rs:+2:2: +2:2 - } - } - diff --git a/tests/mir-opt/deaggregator_test_enum.rs b/tests/mir-opt/deaggregator_test_enum.rs deleted file mode 100644 index ea402dafdec7..000000000000 --- a/tests/mir-opt/deaggregator_test_enum.rs +++ /dev/null @@ -1,19 +0,0 @@ -// unit-test: Deaggregator - -enum Baz { - Empty, - Foo { x: usize }, -} - -// EMIT_MIR deaggregator_test_enum.bar.Deaggregator.diff -fn bar(a: usize) -> Baz { - Baz::Foo { x: a } -} - -fn main() { - let x = bar(10); - match x { - Baz::Empty => println!("empty"), - Baz::Foo { x } => println!("{}", x), - }; -} diff --git a/tests/mir-opt/deaggregator_test_enum_2.rs b/tests/mir-opt/deaggregator_test_enum_2.rs deleted file mode 100644 index 955c317324aa..000000000000 --- a/tests/mir-opt/deaggregator_test_enum_2.rs +++ /dev/null @@ -1,21 +0,0 @@ -// unit-test: Deaggregator -// Test that deaggregate fires in more than one basic block - -enum Foo { - A(i32), - B(i32), -} - -// EMIT_MIR deaggregator_test_enum_2.test1.Deaggregator.diff -fn test1(x: bool, y: i32) -> Foo { - if x { - Foo::A(y) - } else { - Foo::B(y) - } -} - -fn main() { - // Make sure the function actually gets instantiated. - test1(false, 0); -} diff --git a/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff b/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff deleted file mode 100644 index 210d3849e18a..000000000000 --- a/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff +++ /dev/null @@ -1,45 +0,0 @@ -- // MIR for `test1` before Deaggregator -+ // MIR for `test1` after Deaggregator - - fn test1(_1: bool, _2: i32) -> Foo { - debug x => _1; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:10: +0:11 - debug y => _2; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:19: +0:20 - let mut _0: Foo; // return place in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:30: +0:33 - let mut _3: bool; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9 - let mut _4: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17 - let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9 - _3 = _1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9 - switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9 - } - - bb1: { - StorageLive(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17 - _4 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17 -- _0 = Foo::A(move _4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18 -+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18 -+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18 -+ discriminant(_0) = 0; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18 - StorageDead(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:17: +2:18 - goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6 - } - - bb2: { - StorageLive(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17 - _5 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17 -- _0 = Foo::B(move _5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18 -+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18 -+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18 -+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18 - StorageDead(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:17: +4:18 - goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6 - } - - bb3: { - StorageDead(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+5:5: +5:6 - return; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+6:2: +6:2 - } - } - diff --git a/tests/mir-opt/deaggregator_test_multiple.rs b/tests/mir-opt/deaggregator_test_multiple.rs deleted file mode 100644 index 46305fe21d28..000000000000 --- a/tests/mir-opt/deaggregator_test_multiple.rs +++ /dev/null @@ -1,17 +0,0 @@ -// unit-test: Deaggregator -// Test that deaggregate fires more than once per block - -enum Foo { - A(i32), - B, -} - -// EMIT_MIR deaggregator_test_multiple.test.Deaggregator.diff -fn test(x: i32) -> [Foo; 2] { - [Foo::A(x), Foo::A(x)] -} - -fn main() { - // Make sure the function actually gets instantiated. - test(0); -} diff --git a/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff b/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff deleted file mode 100644 index cf5da273c289..000000000000 --- a/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `test` before Deaggregator -+ // MIR for `test` after Deaggregator - - fn test(_1: i32) -> [Foo; 2] { - debug x => _1; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:9: +0:10 - let mut _0: [Foo; 2]; // return place in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:20: +0:28 - let mut _2: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 - let mut _3: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14 - let mut _4: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 - let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 - StorageLive(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14 - _3 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14 -- _2 = Foo::A(move _3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 -+ Deinit(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 -+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 -+ discriminant(_2) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15 - StorageDead(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:14: +1:15 - StorageLive(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 - StorageLive(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25 - _5 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25 -- _4 = Foo::A(move _5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 -+ Deinit(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 -+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 -+ discriminant(_4) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26 - StorageDead(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:25: +1:26 - _0 = [move _2, move _4]; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:5: +1:27 - StorageDead(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27 - StorageDead(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27 - return; // scope 0 at $DIR/deaggregator_test_multiple.rs:+2:2: +2:2 - } - } - diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 9edd1a39f45f..a561798f50fc 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -92,9 +92,7 @@ bb2: { StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 - discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 + _0 = Result::::Err(move _33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 @@ -134,9 +132,7 @@ _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49 StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49 - Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 - ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 - discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 + _3 = ViewportPercentageLength::Vw(move _14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50 StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50 @@ -158,9 +154,7 @@ _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49 StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49 - Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 - ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 - discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 + _3 = ViewportPercentageLength::Vh(move _19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50 StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50 @@ -182,9 +176,7 @@ _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55 StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55 - Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 - ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 - discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 + _3 = ViewportPercentageLength::Vmin(move _24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56 StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56 @@ -206,9 +198,7 @@ _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55 StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55 - Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 - ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 - discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 + _3 = ViewportPercentageLength::Vmax(move _29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56 StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56 @@ -216,9 +206,7 @@ } bb10: { - Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 - ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 - discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 + _0 = Result::::Ok(move _3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2 goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2 diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index 7c5d28069d59..5ebaacd4ba91 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -51,14 +51,20 @@ } bb2: { - Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41 - discriminant(_6) = 1; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41 +- _6 = MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41 ++ _6 = const MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41 ++ // mir::Constant ++ // + span: $DIR/funky_arms.rs:21:17: 21:41 ++ // + literal: Const { ty: Sign, val: Value(Scalar(0x01)) } goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41 } bb3: { - Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38 - discriminant(_6) = 0; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38 +- _6 = Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38 ++ _6 = const Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38 ++ // mir::Constant ++ // + span: $DIR/funky_arms.rs:20:18: 20:38 ++ // + literal: Const { ty: Sign, val: Value(Scalar(0x00)) } goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38 } diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 2f096c3e0a18..7efda05d2b88 100644 --- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -54,9 +54,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24 StorageLive(_6); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 StorageLive(_7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 _7 = (); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 - Deinit(_0); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 - ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 - discriminant(_0) = 0; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 + _0 = GeneratorState::<(), ()>::Yielded(move _7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 return; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18 } diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff index 57574acf9235..593f234f7630 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff @@ -106,9 +106,7 @@ + } + + bb6: { -+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 -+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 -+ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ _1 = GeneratorState::::Yielded(move _8); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 + _11 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 + discriminant((*_11)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 + goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39 @@ -117,9 +115,7 @@ + bb7: { + StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39 -+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 -+ ((_1 as Complete).0: bool) = _7; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 -+ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ _1 = GeneratorState::::Complete(_7); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 + _12 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 + discriminant((*_12)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 + goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41 diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 93804780371c..bcda12880456 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -67,17 +67,14 @@ bb7: { StorageDead(_6); // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36 - Deinit(_0); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 - ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 - discriminant(_0) = 1; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 + _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39 StorageDead(_5); // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39 StorageDead(_4); // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6 goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6 } bb8: { - Deinit(_0); // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13 - discriminant(_0) = 0; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13 + _0 = Option::<[u8; 4]>::None; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13 goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6 } diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 19b726e74845..273639ecd0ba 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -150,8 +150,7 @@ fn array_casts() -> () { bb3: { StorageLive(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_27) = 0; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -164,8 +163,7 @@ fn array_casts() -> () { _33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _34 = Option::>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index e57544e09e2a..cb89d6340760 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -56,36 +56,31 @@ StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 _4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9 _10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -- switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } bb1: { -- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 -- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -- } -- -- bb2: { + StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 + _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + } + + bb2: { StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 _9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 _2 = _9; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10 StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 - discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 + _0 = Result::::Ok(move _2); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11 StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 } -- bb3: { -+ bb2: { + bb3: { unreachable; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 } -- bb4: { -+ bb3: { + bb4: { StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 @@ -97,9 +92,7 @@ _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + _0 = Result::::Err(move _17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 @@ -109,48 +102,33 @@ return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 } -- bb5: { -+ bb4: { + bb5: { StorageLive(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL _13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL _15 = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_14 as Err).0: i32) = move _15; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_14) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL + _14 = Result::::Err(move _15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Break).0: std::result::Result) = move _14; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL + _3 = ControlFlow::, i32>::Break(move _14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 -+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } -- bb6: { -+ bb5: { + bb6: { unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } -- bb7: { -+ bb6: { + bb7: { StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL _11 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL _12 = move _11; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - ((_3 as Continue).0: i32) = move _12; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + _3 = ControlFlow::, i32>::Continue(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL -+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 -+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 -+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } } diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff index 8cc0c6a18353..3c7e9dc61315 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff @@ -38,14 +38,10 @@ _6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18 StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43 _7 = _6; // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43 - Deinit(_2); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 - ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 - discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 + _2 = ControlFlow::::Break(move _7); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44 StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44 StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44 -- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44 -+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 + goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44 } bb2: { @@ -57,53 +53,41 @@ _4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17 StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 _5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45 - Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 - discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 + _2 = ControlFlow::::Continue(move _5); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46 StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46 StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46 -- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46 -- } -- -- bb4: { - _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 -- switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 -+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 + goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46 } -- bb5: { -+ bb4: { + bb4: { + _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 + switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6 + } + + bb5: { StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 _11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29 - Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 - discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 + _0 = Option::::None; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38 StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 -- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 -+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 + goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38 } -- bb6: { -+ bb5: { + bb6: { unreachable; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6 } -- bb7: { -+ bb6: { + bb7: { StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 _9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32 StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 _10 = _9; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43 - Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 - discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 + _0 = Option::::Some(move _10); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44 StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44 StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 -- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 -+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 + goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44 } -- bb8: { -+ bb7: { + bb8: { StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2 return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2 } diff --git a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir index 760f48d956d6..0c2cb95a3555 100644 --- a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir @@ -25,8 +25,7 @@ fn ezmap(_1: Option) -> Option { } bb1: { - Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 - discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + _0 = Option::::None; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 } @@ -38,9 +37,7 @@ fn ezmap(_1: Option) -> Option { _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 _4 = Add(_5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 - Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 - ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 - discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + _0 = Option::::Some(move _4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2 } diff --git a/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff index 981738030186..946595e322e1 100644 --- a/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff @@ -9,8 +9,7 @@ bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 -- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 -- discriminant(_1) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 +- _1 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17 - StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18 _0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2 return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2 diff --git a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff index b152dc8cca3a..f3cf3db8832b 100644 --- a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff @@ -9,12 +9,10 @@ bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 -- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 -- discriminant(_1) = 1; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 +- _1 = E::B; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26 - StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17 - StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 -- Deinit(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 -- discriminant(_3) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 +- _3 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 - Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 - (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 - (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff index f888c622d908..6432a507deb5 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff @@ -18,11 +18,9 @@ bb0: { StorageLive(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 StorageLive(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 - Deinit(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 - discriminant(_2) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 + _2 = Option::::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 - Deinit(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 - discriminant(_3) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 + _3 = Option::::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 (_1.0: std::option::Option) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 (_1.1: std::option::Option) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 diff --git a/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff index 027c983e6b4c..3f9af31d888e 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff @@ -26,9 +26,7 @@ _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15 StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26 _4 = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26 - Deinit(_0); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 - ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 - discriminant(_0) = 1; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 + _0 = Option::>::Some(move _4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27 StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27 @@ -39,8 +37,7 @@ } bb3: { - Deinit(_0); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 - discriminant(_0) = 0; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 + _0 = Option::>::None; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21 } diff --git a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff index a5488c1ec7bf..04d26162aade 100644 --- a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff @@ -16,9 +16,7 @@ StorageLive(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29 StorageLive(_3); // scope 1 at $DIR/sroa.rs:+1:27: +1:28 _3 = _1; // scope 1 at $DIR/sroa.rs:+1:27: +1:28 - Deinit(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29 - ((_2 as Some).0: usize) = move _3; // scope 1 at $DIR/sroa.rs:+1:22: +1:29 - discriminant(_2) = 1; // scope 1 at $DIR/sroa.rs:+1:22: +1:29 + _2 = Option::::Some(move _3); // scope 1 at $DIR/sroa.rs:+1:22: +1:29 StorageDead(_3); // scope 1 at $DIR/sroa.rs:+1:28: +1:29 _4 = discriminant(_2); // scope 1 at $DIR/sroa.rs:+1:12: +1:19 switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19 diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff index d4c04d5e68b8..c3e812f90f5c 100644 --- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff @@ -38,9 +38,7 @@ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 Deinit(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 - Deinit(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 - ((_7 as Some).0: isize) = const -4_isize; // scope 0 at $DIR/sroa.rs:+1:60: +1:68 - discriminant(_7) = 1; // scope 0 at $DIR/sroa.rs:+1:60: +1:68 + _7 = Option::::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 - Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 - (_5.0: u8) = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 - (_5.1: ()) = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 diff --git a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir index a4d2660ca6ae..b9cc1057513d 100644 --- a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir +++ b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir @@ -26,45 +26,40 @@ fn new(_1: Result) -> Result { bb0: { StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 _3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20 - switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20 + switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20 } bb1: { _5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22 - Deinit(_2); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 - ((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 - discriminant(_2) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 - _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 - switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10 + _2 = ControlFlow::::Break(move _5); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48 + goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48 } bb2: { _4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21 - Deinit(_2); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 - ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 - discriminant(_2) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 - _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 - switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10 + _2 = ControlFlow::::Continue(move _4); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50 + goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50 } bb3: { + _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 + switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10 + } + + bb4: { _8 = move ((_2 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33 - Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 - ((_0 as Err).0: E) = move _8; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 - discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 + _0 = Result::::Err(move _8); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51 StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 } - bb4: { + bb5: { unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10 } - bb5: { + bb6: { _7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36 - Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 - ((_0 as Ok).0: T) = move _7; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 - discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 + _0 = Result::::Ok(move _7); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6 StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2 } diff --git a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir index 37851c66a607..d88ae5ac93eb 100644 --- a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir +++ b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir @@ -20,9 +20,7 @@ fn old(_1: Result) -> Result { bb1: { _4 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18 - Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 - ((_0 as Err).0: E) = move _4; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 - discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 + _0 = Result::::Err(move _4); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36 return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2 } @@ -32,9 +30,7 @@ fn old(_1: Result) -> Result { bb3: { _3 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17 - Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 - ((_0 as Ok).0: T) = move _3; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 - discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 + _0 = Result::::Ok(move _3); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6 return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2 } } diff --git a/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 39ec05277595..03f37b14b28c 100644 --- a/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -15,8 +15,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 - Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 - discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 + _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 _3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19 } @@ -33,8 +32,7 @@ fn main() -> () { StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7 StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6 StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 - Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 - discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 + _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 _8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19 } diff --git a/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff index 598413a1d82d..671e116226be 100644 --- a/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff @@ -16,8 +16,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 - Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 - discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 + _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 _3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19 - switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19 + switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19 @@ -62,8 +61,7 @@ StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7 StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6 StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 - Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 - discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 + _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 _8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19 switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19 } diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index c8cd6f6c1ea1..142daf65637e 100644 --- a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -22,8 +22,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 + _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff index 2aee6d2681d6..5c75dc3f6435 100644 --- a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -23,8 +23,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 + _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 diff --git a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir index ee029676311b..8b271135cc3f 100644 --- a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir +++ b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir @@ -4,9 +4,7 @@ fn Test::X(_1: usize) -> Test { let mut _0: Test; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 bb0: { - Deinit(_0); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 - ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 - discriminant(_0) = 0; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 + _0 = Test::X(move _1); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6 } } diff --git a/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff index bb1de59d4a73..a4f2d8c84d88 100644 --- a/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff +++ b/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff @@ -16,8 +16,7 @@ StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19 StorageLive(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - Deinit(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - discriminant(_2) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 + _2 = Option::::None; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - _3 = discriminant(_2); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 - switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 + _3 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 From 134d8190727c6dca40011f03686e7bb68f46a26b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 25 Jan 2023 18:34:19 +0000 Subject: [PATCH 068/137] Stop deaggegating MIR. --- .../rustc_const_eval/src/util/aggregate.rs | 77 ------------------- compiler/rustc_const_eval/src/util/mod.rs | 2 - .../rustc_mir_transform/src/deaggregator.rs | 49 ------------ compiler/rustc_mir_transform/src/lib.rs | 4 - 4 files changed, 132 deletions(-) delete mode 100644 compiler/rustc_const_eval/src/util/aggregate.rs delete mode 100644 compiler/rustc_mir_transform/src/deaggregator.rs diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs deleted file mode 100644 index 10783c5ed1d1..000000000000 --- a/compiler/rustc_const_eval/src/util/aggregate.rs +++ /dev/null @@ -1,77 +0,0 @@ -use rustc_index::vec::Idx; -use rustc_middle::mir::*; -use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; - -use std::iter::TrustedLen; - -/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields. -/// -/// Produces something like -/// ```ignore (ilustrative) -/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum -/// (lhs as Variant).field1 = arg1; -/// discriminant(lhs) = variant_index; // If lhs is an enum or generator. -/// ``` -pub fn expand_aggregate<'tcx>( - orig_lhs: Place<'tcx>, - operands: impl Iterator, Ty<'tcx>)> + TrustedLen, - kind: AggregateKind<'tcx>, - source_info: SourceInfo, - tcx: TyCtxt<'tcx>, -) -> impl Iterator> + TrustedLen { - let mut lhs = orig_lhs; - let mut set_discriminant = None; - let active_field_index = match kind { - AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { - let adt_def = tcx.adt_def(adt_did); - if adt_def.is_enum() { - set_discriminant = Some(Statement { - kind: StatementKind::SetDiscriminant { - place: Box::new(orig_lhs), - variant_index, - }, - source_info, - }); - lhs = tcx.mk_place_downcast(orig_lhs, adt_def, variant_index); - } - active_field_index - } - AggregateKind::Generator(..) => { - // Right now we only support initializing generators to - // variant 0 (Unresumed). - let variant_index = VariantIdx::new(0); - set_discriminant = Some(Statement { - kind: StatementKind::SetDiscriminant { place: Box::new(orig_lhs), variant_index }, - source_info, - }); - - // Operands are upvars stored on the base place, so no - // downcast is necessary. - - None - } - _ => None, - }; - - let operands = operands.enumerate().map(move |(i, (op, ty))| { - let lhs_field = if let AggregateKind::Array(_) = kind { - let offset = u64::try_from(i).unwrap(); - tcx.mk_place_elem( - lhs, - ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false }, - ) - } else { - let field = Field::new(active_field_index.unwrap_or(i)); - tcx.mk_place_field(lhs, field, ty) - }; - Statement { - source_info, - kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))), - } - }); - [Statement { source_info, kind: StatementKind::Deinit(Box::new(orig_lhs)) }] - .into_iter() - .chain(operands) - .chain(set_discriminant) -} diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 76ea5a24e69e..51735e33e0f7 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -1,4 +1,3 @@ -pub mod aggregate; mod alignment; mod call_kind; pub mod collect_writes; @@ -7,7 +6,6 @@ mod find_self_call; mod might_permit_raw_init; mod type_name; -pub use self::aggregate::expand_aggregate; pub use self::alignment::is_disaligned; pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind}; pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs deleted file mode 100644 index 905e127b7cb8..000000000000 --- a/compiler/rustc_mir_transform/src/deaggregator.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::util::expand_aggregate; -use crate::MirPass; -use rustc_hir::def::DefKind; -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; - -pub struct Deaggregator; - -impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); - for bb in basic_blocks { - bb.expand_statements(|stmt| { - // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL). - let StatementKind::Assign(box ( - _, Rvalue::Aggregate(box ref kind, _)) - ) = stmt.kind else { return None }; - - // FIXME(#48193) Deaggregate arrays when it's cheaper to do so. - if let AggregateKind::Array(_) = kind { - return None; - } - - if let AggregateKind::Adt(def_id, ..) = kind - && matches!(tcx.def_kind(def_id), DefKind::Enum) - { - return None; - } - - let stmt = stmt.replace_nop(); - let source_info = stmt.source_info; - let StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) = stmt.kind else { - bug!(); - }; - - Some(expand_aggregate( - lhs, - operands.into_iter().map(|op| { - let ty = op.ty(&body.local_decls, tcx); - (op, ty) - }), - *kind, - source_info, - tcx, - )) - }); - } - } -} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 6815289776e9..9070a7368b16 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -60,7 +60,6 @@ mod coverage; mod ctfe_limit; mod dataflow_const_prop; mod dead_store_elimination; -mod deaggregator; mod deduce_param_attrs; mod deduplicate_blocks; mod deref_separator; @@ -523,9 +522,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &elaborate_box_derefs::ElaborateBoxDerefs, &generator::StateTransform, &add_retag::AddRetag, - // Deaggregator is necessary for const prop. We may want to consider implementing - // CTFE support for aggregates. - &deaggregator::Deaggregator, &Lint(const_prop_lint::ConstProp), ]; pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial))); From 10ec94930b0fa85fea2684a5da4f90376e5633a5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 25 Jan 2023 18:34:35 +0000 Subject: [PATCH 069/137] Bless tests. --- ...primitives.{impl#0}-clone.InstCombine.diff | 5 +- .../const_debuginfo.main.ConstDebugInfo.diff | 73 +++++++------------ ...oto_storage.match_nested_if.ConstGoto.diff | 2 +- .../const_prop/aggregate.main.ConstProp.diff | 5 +- .../aggregate.main.PreCodegen.after.mir | 5 +- .../invalid_constant.main.ConstProp.diff | 6 +- .../issue_66971.main.ConstProp.diff | 7 +- .../issue_67019.main.ConstProp.diff | 9 +-- ...ble_variable_aggregate.main.ConstProp.diff | 5 +- ...able_aggregate_mut_ref.main.ConstProp.diff | 4 +- ...variable_unprop_assign.main.ConstProp.diff | 49 ++++++------- ...es_into_variable.main.ConstProp.64bit.diff | 7 +- ...n.ScalarReplacementOfAggregates.64bit.diff | 21 +----- ...le_literal_propagation.main.ConstProp.diff | 13 +--- .../const_prop_miscompile.bar.ConstProp.diff | 4 +- .../const_prop_miscompile.foo.ConstProp.diff | 4 +- .../copy-prop/issue_107511.main.CopyProp.diff | 4 +- ...pr_transparent.main.DataflowConstProp.diff | 8 +- .../sibling_ptr.main.DataflowConstProp.diff | 4 +- .../struct.main.DataflowConstProp.diff | 3 +- .../tuple.main.DataflowConstProp.diff | 8 +- .../deaggregator_test.bar.Deaggregator.diff | 21 ------ tests/mir-opt/deaggregator_test.rs | 17 ----- ...wise_branch.opt1.EarlyOtherwiseBranch.diff | 4 +- ...wise_branch.opt2.EarlyOtherwiseBranch.diff | 4 +- ...wise_branch.opt3.EarlyOtherwiseBranch.diff | 4 +- ...ement_tuple.opt1.EarlyOtherwiseBranch.diff | 5 +- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 6 +- ...nch_noopt.noopt1.EarlyOtherwiseBranch.diff | 4 +- tests/mir-opt/inline/cycle.f.Inline.diff | 2 +- .../inline_closure.foo.Inline.after.mir | 14 +++- ...e_closure_borrows_arg.foo.Inline.after.mir | 14 +++- ...line_closure_captures.foo.Inline.after.mir | 19 +++-- .../inline/inline_diverging.h.Inline.diff | 4 +- .../inline/inline_generator.main.Inline.diff | 16 +++- .../inline_into_box_place.main.Inline.diff | 4 +- ...ine_scopes_parenting.main.Inline.after.mir | 14 +++- .../inline/issue_78442.bar.Inline.diff | 2 +- .../inline/issue_78442.bar.RevealAll.diff | 2 +- ...f_copy_nonoverlapping.LowerIntrinsics.diff | 4 +- ...ranches.bar.MatchBranchSimplification.diff | 10 +-- ...ranches.foo.MatchBranchSimplification.diff | 2 +- ...h_nested_if.MatchBranchSimplification.diff | 2 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 15 ++-- ...age_markers.main.RemoveStorageMarkers.diff | 4 +- ...remove_zsts.get_union.PreCodegen.after.mir | 5 +- .../remove_zsts.get_union.RemoveZsts.diff | 6 +- ...asts.SimplifyCfg-elaborate-drops.after.mir | 4 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 15 ++-- ..._option_map_e2e.ezmap.PreCodegen.after.mir | 26 +++++-- ...s.d2.SimplifyLocals-before-const-prop.diff | 4 +- ...s_fixedpoint.foo.SimplifyLocals-final.diff | 4 +- ...main.SimplifyLocals-before-const-prop.diff | 30 +++----- ...ropping.ScalarReplacementOfAggregates.diff | 14 +--- ...scaping.ScalarReplacementOfAggregates.diff | 5 +- ...oa.flat.ScalarReplacementOfAggregates.diff | 44 ++--------- ...structs.ScalarReplacementOfAggregates.diff | 21 +----- ....unions.ScalarReplacementOfAggregates.diff | 3 +- ...after-uninhabited-enum-branching.after.mir | 4 +- ...nching2.main.UninhabitedEnumBranching.diff | 4 +- tests/ui/consts/const-err-late.stderr | 12 --- 61 files changed, 234 insertions(+), 406 deletions(-) delete mode 100644 tests/mir-opt/deaggregator_test.bar.Deaggregator.diff delete mode 100644 tests/mir-opt/deaggregator_test.rs diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff index 6f01553eef6d..20b0fb9643ee 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff @@ -61,10 +61,7 @@ bb3: { StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16 - Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15 - (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15 - (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15 - (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15 + _0 = MyThing:: { v: move _2, i: move _5, a: move _8 }; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15 StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15 StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15 StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15 diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index f4e9d53286f5..49e8b020dfb7 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -8,8 +8,8 @@ let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16 let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20 let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24 - let mut _12: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 - let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 + let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 + let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 scope 1 { - debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 + debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 @@ -29,21 +29,18 @@ scope 5 { - debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 + debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 - let _14: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _15: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _16: u32; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 scope 6 { - debug f => (bool, bool, u32){ .0 => _14, .1 => _15, .2 => _16, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _10: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + debug f => _10; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 scope 7 { - debug o => _10; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 - let _17: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _18: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 + let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 scope 8 { - debug p => Point{ .0 => _17, .1 => _18, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _11: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug p => _12; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 scope 9 { -- debug a => _11; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 +- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 } } @@ -69,38 +66,24 @@ // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 // + literal: Const { ty: &str, val: Value(Slice(..)) } - StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - Deinit(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - Deinit(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - Deinit(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 - _10 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - Deinit(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - _17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - _18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 - StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - _12 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _13 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 - StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_16); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + _10 = (const true, const false, const 123_u32); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + _11 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + _12 = Point { x: const 32_u32, y: const 32_u32 }; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 + _14 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 + StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 + _15 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 + _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 + StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 + StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 + StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2 return; // scope 0 at $DIR/const_debuginfo.rs:+14:2: +14:2 diff --git a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff b/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff index f54577259431..4dc98f856740 100644 --- a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff +++ b/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff @@ -17,7 +17,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_goto_storage.rs:+1:9: +1:12 - StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23 -- Deinit(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23 +- _2 = (); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23 - StorageLive(_3); // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10 - StorageLive(_4); // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76 - StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52 diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff index 04378dbf374d..6ad405757a6a 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -14,10 +14,7 @@ StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + _3 = (const 0_i32, const 1_i32, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 + _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir index cfc9a72e3b22..920d73f8a596 100644 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir +++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir @@ -13,10 +13,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + _3 = (const 0_i32, const 1_i32, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 diff --git a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index 6c4757c1a810..4f056dd85e3f 100644 --- a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -32,16 +32,14 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22 StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 + _2 = InvalidChar { int: const 1114113_u32 }; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 + _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70 StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59 StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 + _5 = InvalidTag { int: const 4_u32 }; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 - _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 + _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 488e772d0ea8..964dd3080749 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -5,13 +5,14 @@ let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11 let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 bb0: { StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 + _2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 + StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22 _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 // mir::Constant // + span: $DIR/issue_66971.rs:17:5: 17:11 diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff index cd53048597b8..a631cb310904 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -11,12 +11,9 @@ StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 - Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 - (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 - (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 - Deinit(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 -- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 -+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 +- _3 = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 ++ _3 = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17 + _2 = (move _3,); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19 StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19 _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 // mir::Constant diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index f6bf522065ba..0eb47087c9c7 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -14,9 +14,8 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 +- _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 ++ _1 = const (42_i32, 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index 213a70227d87..26a1c3c1aa9e 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -18,9 +18,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 - (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 - (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 + _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19 ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index c3f77b960a2d..a2e4890c6a64 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -4,19 +4,18 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 scope 1 { debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _5: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let mut _6: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 scope 2 { - debug x => (i32, i32){ .0 => _5, .1 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let _3: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 scope 3 { - debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 scope 4 { - debug z => _4; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 } } } @@ -31,25 +30,21 @@ } bb1: { - StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - Deinit(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - Deinit(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - _5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - _6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _2 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _6 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 - StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - _3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 - StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 -- _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 -+ _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 - StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 +- _2 = (const 1_i32, const 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 ++ _2 = const (1_i32, 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 + StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 +- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 ++ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 } diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index 7c7aeac4c451..1368b114658d 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -52,9 +52,8 @@ StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff index 3f9f3b2eac71..de1d57ed401a 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff @@ -10,8 +10,6 @@ let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -47,21 +45,10 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 -- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 -+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 -+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index e4c92b617c6a..270a1ccf560f 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -11,24 +11,17 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 - (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 - (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 +- _1 = (const 1_u32, const 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 ++ _1 = const (1_u32, 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 - StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 -- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 -+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 - _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 + _2 = consume(_1) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 // mir::Constant // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value() } } bb1: { - StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15 StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16 - StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2 return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2 } } diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff index b6b542fb7943..def9fc6428fb 100644 --- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -19,8 +19,8 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 - (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 +- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 ++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff index e43735fd9e14..b54c10a140f2 100644 --- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -16,8 +16,8 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 - (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 +- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 ++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 _2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14 (*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18 diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff index 28ba651ad4ae..97d0a01e00bc 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff @@ -57,9 +57,7 @@ bb1: { StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 - Deinit(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - (_4.0: usize) = const 0_usize; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 - (_4.1: usize) = move _5; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 + _4 = std::ops::Range:: { start: const 0_usize, end: move _5 }; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 _3 = as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 // mir::Constant diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index f66b00a9a224..8f045eedfb05 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -17,8 +17,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19 - (_1.0: i32) = const 0_i32; // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19 + _1 = I32(const 0_i32); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19 StorageLive(_2); // scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10 StorageLive(_3); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26 StorageLive(_4); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20 @@ -31,9 +30,8 @@ + _3 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26 StorageDead(_5); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26 StorageDead(_4); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26 - Deinit(_2); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 -- (_2.0: i32) = move _3; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 -+ (_2.0: i32) = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 +- _2 = I32(move _3); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 ++ _2 = I32(const 0_i32); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 StorageDead(_3); // scope 1 at $DIR/repr_transparent.rs:+2:26: +2:27 _0 = const (); // scope 0 at $DIR/repr_transparent.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/repr_transparent.rs:+3:1: +3:2 diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff index 8126d4b8585e..a91a755830d1 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff @@ -23,9 +23,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 - (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 - (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 + _1 = (const 0_u8, const 0_u8); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6 StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14 _3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff index cfb2706c167c..53c62c081739 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff @@ -21,8 +21,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21 - (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21 + _1 = S(const 1_i32); // scope 0 at $DIR/struct.rs:+1:17: +1:21 StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10 StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16 - _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16 diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff index e028def00a11..8ce4ce4ba976 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff @@ -25,9 +25,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/tuple.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23 - (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 - (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 + _1 = (const 1_i32, const 2_i32); // scope 0 at $DIR/tuple.rs:+1:17: +1:23 StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:10 StorageLive(_3); // scope 1 at $DIR/tuple.rs:+2:13: +2:22 StorageLive(_4); // scope 1 at $DIR/tuple.rs:+2:13: +2:16 @@ -43,9 +41,7 @@ - _2 = Add(move _3, const 3_i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:26 + _2 = const 6_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:26 StorageDead(_3); // scope 1 at $DIR/tuple.rs:+2:25: +2:26 - Deinit(_1); // scope 2 at $DIR/tuple.rs:+3:5: +3:15 - (_1.0: i32) = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15 - (_1.1: i32) = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15 + _1 = (const 2_i32, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:5: +3:15 StorageLive(_6); // scope 2 at $DIR/tuple.rs:+4:9: +4:10 StorageLive(_7); // scope 2 at $DIR/tuple.rs:+4:13: +4:22 StorageLive(_8); // scope 2 at $DIR/tuple.rs:+4:13: +4:16 diff --git a/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff b/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff deleted file mode 100644 index db136485a211..000000000000 --- a/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff +++ /dev/null @@ -1,21 +0,0 @@ -- // MIR for `bar` before Deaggregator -+ // MIR for `bar` after Deaggregator - - fn bar(_1: usize) -> Baz { - debug a => _1; // in scope 0 at $DIR/deaggregator_test.rs:+0:8: +0:9 - let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test.rs:+0:21: +0:24 - let mut _2: usize; // in scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15 - _2 = _1; // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15 -- _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35 -+ Deinit(_0); // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35 -+ (_0.0: usize) = move _2; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35 -+ (_0.1: f32) = const 0f32; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35 -+ (_0.2: bool) = const false; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35 - StorageDead(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:34: +1:35 - return; // scope 0 at $DIR/deaggregator_test.rs:+2:2: +2:2 - } - } - diff --git a/tests/mir-opt/deaggregator_test.rs b/tests/mir-opt/deaggregator_test.rs deleted file mode 100644 index ee59402af386..000000000000 --- a/tests/mir-opt/deaggregator_test.rs +++ /dev/null @@ -1,17 +0,0 @@ -// unit-test: Deaggregator - -struct Baz { - x: usize, - y: f32, - z: bool, -} - -// EMIT_MIR deaggregator_test.bar.Deaggregator.diff -fn bar(a: usize) -> Baz { - Baz { x: a, y: 0.0, z: false } -} - -fn main() { - // Make sure the function actually gets instantiated. - bar(0); -} diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 98a02ee38dd1..5383d1be1298 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -25,9 +25,7 @@ _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13 StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 _5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 - Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 + _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 _7 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index aa75c44b809a..b3e21ff49bdf 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -26,9 +26,7 @@ _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13 StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 _5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 - Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 + _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 _8 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index cea6ff7cd05e..e098a88eb557 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -25,9 +25,7 @@ _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13 StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 _5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16 - Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 - (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 + _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17 _7 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17 diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index b90d70ce43aa..ec3b4bbdff42 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -34,10 +34,7 @@ _6 = _2; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:15: +1:16 StorageLive(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19 _7 = _3; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19 - Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20 - (_4.0: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20 - (_4.1: std::option::Option) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20 - (_4.2: std::option::Option) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20 + _4 = (move _5, move _6, move _7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20 StorageDead(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20 StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20 diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index a561798f50fc..a91d0d7cf730 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -73,9 +73,7 @@ _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16 StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23 _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23 - Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 - (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 + _4 = (move _5, move _6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24 _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24 @@ -91,7 +89,7 @@ bb2: { StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 - Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 + _33 = (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27 _0 = Result::::Err(move _33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28 StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7 diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 82d8b2fc5a46..6468eb5f8dde 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -32,9 +32,7 @@ _4 = _1; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:12: +1:13 StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16 _5 = _2; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16 - Deinit(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17 - (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17 - (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17 + _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17 _8 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17 diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff index 75ea69a42eb5..501390c3bf10 100644 --- a/tests/mir-opt/inline/cycle.f.Inline.diff +++ b/tests/mir-opt/inline/cycle.f.Inline.diff @@ -13,7 +13,7 @@ StorageLive(_3); // scope 0 at $DIR/cycle.rs:+1:5: +1:6 _3 = &_1; // scope 0 at $DIR/cycle.rs:+1:5: +1:6 StorageLive(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 - Deinit(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 + _4 = (); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 _2 = >::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8 // mir::Constant // + span: $DIR/cycle.rs:6:5: 6:6 diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir index 9eb3a01eef91..fff8d0171277 100644 --- a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -21,7 +21,15 @@ fn foo(_1: T, _2: i32) -> i32 { bb0: { StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 - Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24 + _3 = [closure@foo::::{closure#0}]; // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24 + // closure + // + def_id: DefId(0:6 ~ inline_closure[92ba]::foo::{closure#0}) + // + substs: [ + // T, + // i8, + // extern "rust-call" fn((i32, i32)) -> i32, + // (), + // ] StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 _4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 @@ -29,9 +37,7 @@ fn foo(_1: T, _2: i32) -> i32 { _6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8 StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 _7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 - Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 - (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 - (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 _8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index dd32eb2d8d1f..dab2043064f3 100644 --- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -24,7 +24,15 @@ fn foo(_1: T, _2: &i32) -> i32 { bb0: { StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 - Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6 + _3 = [closure@foo::::{closure#0}]; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6 + // closure + // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[96e9]::foo::{closure#0}) + // + substs: [ + // T, + // i8, + // for<'a, 'b> extern "rust-call" fn((&'a i32, &'b i32)) -> i32, + // (), + // ] StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 _4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 @@ -32,9 +40,7 @@ fn foo(_1: T, _2: &i32) -> i32 { _6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 _7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 - Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 - (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 - (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 _8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index fd19c288666b..84fd051e0a35 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -30,9 +30,15 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 _5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 - Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 - (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 - (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + _3 = [closure@foo::::{closure#0}] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + // closure + // + def_id: DefId(0:6 ~ inline_closure_captures[8bc0]::foo::{closure#0}) + // + substs: [ + // T, + // i8, + // extern "rust-call" fn((i32,)) -> (i32, T), + // (&i32, &T), + // ] StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6 @@ -40,8 +46,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) { StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 _8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 - Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 - (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + _7 = (move _8,); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 _9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 @@ -50,9 +55,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) { StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 _13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 _11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 - Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 - (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 - (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + _0 = (move _10, move _11); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff index f82fcf4c8212..e1b2f7dbf358 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff @@ -48,9 +48,7 @@ + StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 + StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 + _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 -+ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 -+ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 -+ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ _1 = (move _8, move _9); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 + StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11 + StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff index 593f234f7630..95d649f89ba6 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff @@ -44,8 +44,17 @@ - } - - bb1: { -+ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 -+ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 ++ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 ++ // generator ++ // + def_id: DefId(0:7 ~ inline_generator[ea31]::g::{closure#0}) ++ // + substs: [ ++ // bool, ++ // i32, ++ // bool, ++ // {bool, i32}, ++ // (), ++ // ] ++ // + movability: Movable _3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 - _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 - // mir::Constant @@ -59,8 +68,7 @@ + _5 = move _3; // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL -+ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _6 }; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32 diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff index a28da146e378..a1cbf0d3e0dd 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff @@ -51,9 +51,7 @@ + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } -+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ (_9.0: alloc::raw_vec::RawVec) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _9 = Vec:: { buf: move _10, len: const 0_usize }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index d99ae1a6c7c8..4dd1aad489dd 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -20,14 +20,20 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33 + _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33 + // closure + // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[bc59]::main::{closure#0}) + // + substs: [ + // i8, + // extern "rust-call" fn(((),)), + // (), + // ] StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 _2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 - Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 - Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 - (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + _4 = (); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + _3 = (move _4,); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 _5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff index 51a98465fd9a..aa62e4a165e1 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff @@ -25,7 +25,7 @@ bb1: { _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - // mir::Constant - // + span: $DIR/issue_78442.rs:11:5: 11:15 diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff index e47466c5e804..21055c6bfb57 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -24,7 +24,7 @@ bb1: { _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 // mir::Constant diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff index ec15fd1ef74d..5c972a00e464 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff @@ -25,9 +25,9 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12 - Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17 + _1 = (); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17 StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16 - Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21 + _2 = (); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21 StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59 StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45 diff --git a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff index be91b0bfe682..92f8d4e14abb 100644 --- a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff @@ -41,7 +41,7 @@ - _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22 - _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22 - _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21 -- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 +- _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15 - } - @@ -54,7 +54,7 @@ + _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21 _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22 _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21 - Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 + _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15 - } - @@ -69,11 +69,7 @@ _9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13 StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16 _10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16 - Deinit(_0); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 - (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 + _0 = (move _7, move _8, move _9, move _10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17 StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17 diff --git a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff index aa8092ece663..0580f73341d2 100644 --- a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff @@ -34,7 +34,7 @@ - } - - bb4: { - Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11 + _0 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11 - goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 + goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6 } diff --git a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff index 193104dd30e7..20e8ef2f7202 100644 --- a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff @@ -20,7 +20,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12 StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 - Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 + _2 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23 StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10 StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76 StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52 diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir index e522534867d5..210f178a0a9e 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir @@ -16,20 +16,15 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14 StorageLive(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 StorageLive(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 - Deinit(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 - (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 - Deinit(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 - (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 + _3 = Droppy(const 0_usize); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41 + _2 = Aligned(move _3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42 StorageDead(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:41: +1:42 - Deinit(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43 - (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43 + _1 = Packed(move _2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43 StorageDead(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:42: +1:43 StorageLive(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 StorageLive(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 - Deinit(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 - (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 - Deinit(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 - (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 + _5 = Droppy(const 0_usize); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28 + _4 = Aligned(move _5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29 StorageDead(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29 StorageLive(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 _6 = move (_1.0: Aligned); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index ed1d0b87f603..a8dd91efc379 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -31,9 +31,7 @@ _1 = const 0_i32; // scope 0 at $DIR/remove_storage_markers.rs:+1:19: +1:20 - StorageLive(_2); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 - StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 - Deinit(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 - (_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 - (_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 + _3 = std::ops::Range:: { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 _2 = as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 // mir::Constant // + span: $DIR/remove_storage_markers.rs:10:14: 10:19 diff --git a/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir b/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir index 12e914e25e0c..af34bc5edb7f 100644 --- a/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir +++ b/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir @@ -2,9 +2,12 @@ fn get_union() -> Foo { let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22 + let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 bb0: { - Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 + StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 + _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 + StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18 return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2 } } diff --git a/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff b/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff index 169b7b1054b4..0af29b2babc2 100644 --- a/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff +++ b/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff @@ -7,11 +7,9 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 -- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 +- _1 = (); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 + nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 - Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 -- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 -+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 + _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18 return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2 } diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 273639ecd0ba..3b479710b4f2 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -122,9 +122,7 @@ fn array_casts() -> () { // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index b853e4505417..d7b6d64b6b7b 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -62,8 +62,7 @@ fn main() -> () { StorageLive(_3); // scope 1 at $DIR/retag.rs:+3:13: +3:14 StorageLive(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36 StorageLive(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24 - Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24 - (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24 + _5 = Test(const 0_i32); // scope 1 at $DIR/retag.rs:+3:17: +3:24 _4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36 StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35 StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 @@ -107,7 +106,14 @@ fn main() -> () { StorageDead(_2); // scope 1 at $DIR/retag.rs:+8:5: +8:6 StorageLive(_13); // scope 1 at $DIR/retag.rs:+11:9: +11:10 StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 - Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 + _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:+11:31: +14:6 + // closure + // + def_id: DefId(0:14 ~ retag[4622]::main::{closure#0}) + // + substs: [ + // i8, + // for<'a> extern "rust-call" fn((&'a i32,)) -> &'a i32, + // (), + // ] Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6 StorageDead(_14); // scope 1 at $DIR/retag.rs:+11:47: +11:48 @@ -129,8 +135,7 @@ fn main() -> () { StorageLive(_19); // scope 7 at $DIR/retag.rs:+18:5: +18:24 StorageLive(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24 StorageLive(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12 - Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12 - (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12 + _21 = Test(const 0_i32); // scope 7 at $DIR/retag.rs:+18:5: +18:12 _20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24 StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23 StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 diff --git a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir index 0c2cb95a3555..5c898d798ff1 100644 --- a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir @@ -4,22 +4,25 @@ fn ezmap(_1: Option) -> Option { debug x => _1; // in scope 0 at $DIR/simple_option_map_e2e.rs:+0:14: +0:15 let mut _0: std::option::Option; // return place in scope 0 at $DIR/simple_option_map_e2e.rs:+0:33: +0:44 let mut _2: [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]; // in scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + let mut _7: i32; // in scope 0 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 scope 1 (inlined map::) { // at $DIR/simple_option_map_e2e.rs:14:5: 14:22 debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20 debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34 let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16 - let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + let _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + let mut _6: (i32,); // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 scope 2 { - debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + debug x => _4; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 + debug n => _7; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 } } } bb0: { StorageLive(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + StorageLive(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22 _3 = discriminant(_1); // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map_e2e.rs:6:5: 6:14 } @@ -34,15 +37,22 @@ fn ezmap(_1: Option) -> Option { } bb3: { - _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 - StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - _4 = Add(_5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 - _0 = Option::::Some(move _4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 - StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 + _4 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + StorageLive(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + _6 = (move _4,); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + StorageLive(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + _7 = move (_6.0: i32); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + _5 = Add(_7, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 + StorageDead(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + StorageDead(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:28: 7:29 + _0 = Option::::Some(move _5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + StorageDead(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2 } bb4: { + StorageDead(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22 StorageDead(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:21: +1:22 return; // scope 0 at $DIR/simple_option_map_e2e.rs:+2:2: +2:2 } diff --git a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff index f3cf3db8832b..6a5dc56e211c 100644 --- a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff @@ -13,9 +13,7 @@ - StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17 - StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 - _3 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15 -- Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 -- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 -- (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 +- _2 = (const 10_i32, move _3); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16 - StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16 - (_2.1: E) = move _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:26 - StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:25: +2:26 diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff index 6432a507deb5..9b7dd7338203 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff @@ -21,9 +21,7 @@ _2 = Option::::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49 StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 _3 = Option::::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68 - Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 - (_1.0: std::option::Option) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 - (_1.1: std::option::Option) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 + _1 = (move _2, move _3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69 StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69 StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69 _5 = discriminant((_1.0: std::option::Option)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27 diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff index efb2b0961cc1..0f8866f9c2f4 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff @@ -28,36 +28,30 @@ bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 - StorageLive(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 -- Deinit(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 +- _2 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23 - StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 -- Deinit(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 -- Deinit(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 -- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 -- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 +- _3 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27 +- _1 = (move _2, move _3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28 - StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28 - StorageDead(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28 - StorageDead(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:28: +1:29 - StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 - StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 - StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 -- Deinit(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 +- _6 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 - StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 -- Deinit(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 -- Deinit(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 -- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 -- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 +- _7 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 +- _5 = (move _6, move _7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 - StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 - StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 - _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 + StorageLive(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 + StorageLive(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 + StorageLive(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 -+ Deinit(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 ++ _3 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16 + StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 -+ Deinit(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 -+ Deinit(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 -+ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 -+ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 ++ _4 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20 ++ _2 = (move _3, move _4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21 + StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 + StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 + _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 @@ -73,8 +67,7 @@ - StorageLive(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 - StorageLive(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 - StorageLive(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 -- Deinit(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 -- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 +- _11 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 - _10 = (_11.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 - _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 - StorageDead(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34 @@ -85,8 +78,7 @@ + StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 + StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 + StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 -+ Deinit(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 -+ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 ++ _8 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28 + _7 = (_8.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30 + _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34 + StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34 diff --git a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff index eb88304466ee..17a89e7d8eb2 100644 --- a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff @@ -13,18 +13,12 @@ StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:32 StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13 - Deinit(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13 - (_3.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+1:7: +1:13 + _3 = Tag(const 0_usize); // scope 0 at $DIR/sroa.rs:+1:7: +1:13 StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21 - Deinit(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21 - (_4.0: usize) = const 1_usize; // scope 0 at $DIR/sroa.rs:+1:15: +1:21 + _4 = Tag(const 1_usize); // scope 0 at $DIR/sroa.rs:+1:15: +1:21 StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29 - Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29 - (_5.0: usize) = const 2_usize; // scope 0 at $DIR/sroa.rs:+1:23: +1:29 - Deinit(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30 - (_2.0: Tag) = move _3; // scope 0 at $DIR/sroa.rs:+1:5: +1:30 - (_2.1: Tag) = move _4; // scope 0 at $DIR/sroa.rs:+1:5: +1:30 - (_2.2: Tag) = move _5; // scope 0 at $DIR/sroa.rs:+1:5: +1:30 + _5 = Tag(const 2_usize); // scope 0 at $DIR/sroa.rs:+1:23: +1:29 + _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/sroa.rs:+1:5: +1:30 StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:29: +1:30 StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:29: +1:30 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:29: +1:30 diff --git a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff index 64559b58f61f..b01fb6fc9153 100644 --- a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff @@ -22,10 +22,7 @@ } bb1: { - Deinit(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39 - (_4.0: u32) = const 1_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39 - (_4.1: u32) = const 2_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39 - (_4.2: u32) = move _5; // scope 0 at $DIR/sroa.rs:+2:8: +2:39 + _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+2:8: +2:39 StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39 _3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41 _2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41 diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff index c3e812f90f5c..749c22c26e04 100644 --- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff @@ -10,10 +10,6 @@ let mut _5: Foo; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 let mut _6: (); // in scope 0 at $DIR/sroa.rs:+1:45: +1:47 let mut _7: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:60: +1:68 -+ let mut _8: u8; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ let mut _9: (); // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ let mut _10: &str; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ let mut _11: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 scope 1 { debug a => _1; // in scope 1 at $DIR/sroa.rs:+1:15: +1:16 debug b => _2; // in scope 1 at $DIR/sroa.rs:+1:18: +1:19 @@ -30,50 +26,26 @@ } bb0: { -- StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ StorageLive(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ StorageLive(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 + StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 - Deinit(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 + _6 = (); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 _7 = Option::::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 -- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -- (_5.0: u8) = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -- (_5.1: ()) = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -- (_5.2: &str) = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ Deinit(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ Deinit(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ Deinit(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ Deinit(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ _8 = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 + _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 // mir::Constant // + span: $DIR/sroa.rs:57:52: 57:55 // + literal: Const { ty: &str, val: Value(Slice(..)) } -- (_5.3: std::option::Option) = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 -+ _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 StorageDead(_7); // scope 0 at $DIR/sroa.rs:+1:69: +1:70 StorageDead(_6); // scope 0 at $DIR/sroa.rs:+1:69: +1:70 StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 -- _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 -+ _1 = _8; // scope 0 at $DIR/sroa.rs:+1:15: +1:16 + _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 -- _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 -+ _2 = _9; // scope 0 at $DIR/sroa.rs:+1:18: +1:19 + _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 -- _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 -+ _3 = _10; // scope 0 at $DIR/sroa.rs:+1:21: +1:22 + _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 -- _4 = (_5.3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 -- StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 -+ _4 = _11; // scope 0 at $DIR/sroa.rs:+1:24: +1:25 -+ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 -+ StorageDead(_9); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 -+ StorageDead(_10); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 -+ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 + _4 = (_5.3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 + StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 _0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +6:2 StorageDead(_4); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 diff --git a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff index 69d74c351dec..dc4945104f4c 100644 --- a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff @@ -6,28 +6,15 @@ let mut _0: f32; // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:30 let mut _2: structs::U; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 let mut _3: f32; // in scope 0 at $DIR/sroa.rs:+6:18: +6:19 -+ let mut _4: usize; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ let mut _5: f32; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 bb0: { -- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 + StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19 _3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19 -- Deinit(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -- (_2.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -- (_2.1: f32) = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ Deinit(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ Deinit(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ _4 = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ _5 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 + _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21 -- _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23 -- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 -+ _0 = _5; // scope 0 at $DIR/sroa.rs:+6:5: +6:23 -+ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 -+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 + _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23 + StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2 } } diff --git a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff index 03ca976df7be..adfb01385d44 100644 --- a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff @@ -13,8 +13,7 @@ StorageLive(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27 StorageLive(_3); // scope 1 at $DIR/sroa.rs:+5:24: +5:25 _3 = _1; // scope 1 at $DIR/sroa.rs:+5:24: +5:25 - Deinit(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27 - (_2.0: f32) = move _3; // scope 1 at $DIR/sroa.rs:+5:14: +5:27 + _2 = Repr { f: move _3 }; // scope 1 at $DIR/sroa.rs:+5:14: +5:27 StorageDead(_3); // scope 1 at $DIR/sroa.rs:+5:26: +5:27 _0 = (_2.1: u32); // scope 1 at $DIR/sroa.rs:+5:14: +5:29 StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 142daf65637e..eb2a76ed1d5e 100644 --- a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -23,9 +23,7 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 - (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 - (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 + _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48 StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6 StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22 diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff index 5c75dc3f6435..4e797774dba7 100644 --- a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -24,9 +24,7 @@ StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46 - Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 - (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 - (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 + _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48 StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48 StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6 StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22 diff --git a/tests/ui/consts/const-err-late.stderr b/tests/ui/consts/const-err-late.stderr index c5c668189b95..cb0cab2444bf 100644 --- a/tests/ui/consts/const-err-late.stderr +++ b/tests/ui/consts/const-err-late.stderr @@ -28,24 +28,12 @@ note: erroneous constant used LL | black_box((S::::FOO, S::::FOO)); | ^^^^^^^^^^^^^ -note: erroneous constant used - --> $DIR/const-err-late.rs:19:31 - | -LL | black_box((S::::FOO, S::::FOO)); - | ^^^^^^^^^^^^^ - note: erroneous constant used --> $DIR/const-err-late.rs:19:16 | LL | black_box((S::::FOO, S::::FOO)); | ^^^^^^^^^^^^^ -note: erroneous constant used - --> $DIR/const-err-late.rs:19:31 - | -LL | black_box((S::::FOO, S::::FOO)); - | ^^^^^^^^^^^^^ - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. From 83173c68f5f938481a61ba370b2ef11556163ece Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 29 Jan 2023 12:50:27 +0000 Subject: [PATCH 070/137] Add partial propagation test. --- .../const_prop/aggregate.foo.ConstProp.diff | 55 +++++++++++++++++++ .../aggregate.foo.PreCodegen.after.mir | 49 +++++++++++++++++ .../const_prop/aggregate.main.ConstProp.diff | 37 +++++++++---- .../aggregate.main.PreCodegen.after.mir | 32 ++++++++--- tests/mir-opt/const_prop/aggregate.rs | 9 +++ 5 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff create mode 100644 tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir diff --git a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff new file mode 100644 index 000000000000..6ac460db86f8 --- /dev/null +++ b/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff @@ -0,0 +1,55 @@ +- // MIR for `foo` before ConstProp ++ // MIR for `foo` after ConstProp + + fn foo(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9 + let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15 + let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14 + let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25 + let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26 + let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24 + let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20 + scope 1 { + debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14 + let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15 + scope 2 { + debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15 + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14 + StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25 + StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23 +- _3 = (_4.0: i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25 +- _2 = Add(move _3, const 1_i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:29 ++ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25 ++ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29 + StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29 + StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30 + StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15 + StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26 + StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24 + StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20 + _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20 + _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24 + StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24 +- _7 = (_8.1: i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26 +- _6 = Add(move _7, const 2_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:30 ++ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26 ++ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30 + StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30 + StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2 + StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2 + StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2 + return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir new file mode 100644 index 000000000000..2ef6d74e5284 --- /dev/null +++ b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir @@ -0,0 +1,49 @@ +// MIR for `foo` after PreCodegen + +fn foo(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9 + let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15 + let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14 + let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25 + let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26 + let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24 + let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20 + scope 1 { + debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14 + let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15 + scope 2 { + debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15 + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14 + StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25 + StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22 + _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23 + StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23 + _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25 + _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29 + StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29 + StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30 + StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15 + StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26 + StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24 + StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20 + _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20 + _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24 + StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24 + _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26 + _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30 + StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30 + StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2 + StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2 + StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2 + return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2 + } +} diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff index 6ad405757a6a..f6e58955b4f6 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -3,9 +3,11 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 + let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 + let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11 + let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10 scope 1 { debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10 } @@ -14,16 +16,29 @@ StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - _3 = (const 0_i32, const 1_i32, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 -- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 -- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 -+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 -+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 + _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 +- _2 = (_3.1: u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 +- _1 = Add(move _2, const 0_u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 ++ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 ++ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29 - _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2 - return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2 + StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 + StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 +- _5 = _1; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 ++ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 + _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 + // mir::Constant + // + span: $DIR/aggregate.rs:8:5: 8:8 + // + literal: Const { ty: fn(u8) {foo}, val: Value() } + } + + bb1: { + StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11 + StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2 + return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2 } } diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir index 920d73f8a596..4706af92cba9 100644 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir +++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir @@ -2,9 +2,11 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 + let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 + let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11 + let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10 scope 1 { debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10 } @@ -13,13 +15,25 @@ fn main() -> () { StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - _3 = (const 0_i32, const 1_i32, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 + _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 + _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29 - _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2 - return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2 + StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 + StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 + _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 + _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 + // mir::Constant + // + span: $DIR/aggregate.rs:8:5: 8:8 + // + literal: Const { ty: fn(u8) {foo}, val: Value() } + } + + bb1: { + StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11 + StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2 + return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2 } } diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs index 6a3080384daf..aa123b7a8664 100644 --- a/tests/mir-opt/const_prop/aggregate.rs +++ b/tests/mir-opt/const_prop/aggregate.rs @@ -5,4 +5,13 @@ // EMIT_MIR aggregate.main.PreCodegen.after.mir fn main() { let x = (0, 1, 2).1 + 0; + foo(x); +} + +// EMIT_MIR aggregate.foo.ConstProp.diff +// EMIT_MIR aggregate.foo.PreCodegen.after.mir +fn foo(x: u8) { + // Verify that we still propagate if part of the aggregate is not known. + let first = (0, x).0 + 1; + let second = (x, 1).1 + 2; } From 473d0c551006f838f69dfadcc1965492849cfc79 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Feb 2023 18:59:27 +0000 Subject: [PATCH 071/137] Introduce write_aggregate. --- .../rustc_const_eval/src/interpret/place.rs | 28 +++++++++++++++++++ .../rustc_const_eval/src/interpret/step.rs | 20 +------------ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5c00dc21d04e..8d4d0420cda4 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -846,6 +846,34 @@ where Ok(()) } + /// Writes the discriminant of the given variant. + #[instrument(skip(self), level = "debug")] + pub fn write_aggregate( + &mut self, + kind: &mir::AggregateKind<'tcx>, + operands: &[mir::Operand<'tcx>], + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + self.write_uninit(&dest)?; + let (variant_index, variant_dest, active_field_index) = match *kind { + mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { + let variant_dest = self.place_downcast(&dest, variant_index)?; + (variant_index, variant_dest, active_field_index) + } + _ => (VariantIdx::from_u32(0), dest.clone(), None), + }; + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } + for (field_index, operand) in operands.iter().enumerate() { + let field_index = active_field_index.unwrap_or(field_index); + let field_dest = self.place_field(&variant_dest, field_index)?; + let op = self.eval_operand(operand, Some(field_dest.layout))?; + self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; + } + self.write_discriminant(variant_index, &dest) + } + pub fn raw_const_to_mplace( &self, raw: ConstAlloc<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 7e00d90342e1..7d9a98da08a9 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -7,7 +7,6 @@ use either::Either; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use rustc_target::abi::VariantIdx; use super::{ImmTy, InterpCx, Machine}; @@ -200,24 +199,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Aggregate(box ref kind, ref operands) => { - self.write_uninit(&dest)?; - let (variant_index, variant_dest, active_field_index) = match *kind { - mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { - let variant_dest = self.place_downcast(&dest, variant_index)?; - (variant_index, variant_dest, active_field_index) - } - _ => (VariantIdx::from_u32(0), dest.clone(), None), - }; - if active_field_index.is_some() { - assert_eq!(operands.len(), 1); - } - for (field_index, operand) in operands.iter().enumerate() { - let field_index = active_field_index.unwrap_or(field_index); - let field_dest = self.place_field(&variant_dest, field_index)?; - let op = self.eval_operand(operand, Some(field_dest.layout))?; - self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; - } - self.write_discriminant(variant_index, &dest)?; + self.write_aggregate(kind, operands, &dest)?; } Repeat(ref operand, _) => { From 5c39ba20279e338e2cd421bc799d4a5d3397c3b9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Feb 2023 19:08:53 +0000 Subject: [PATCH 072/137] Bless 32bit. --- ...nst_allocation.main.ConstProp.after.32bit.mir | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index 6140fc52f650..9b69f79c28ee 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -26,17 +26,17 @@ alloc1 (static: FOO, size: 8, align: 4) { alloc18 (size: 48, align: 4) { 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼.... } alloc5 (size: 0, align: 4) {} -alloc9 (size: 16, align: 4) { - ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +alloc8 (size: 16, align: 4) { + ╾─alloc9──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc8 (size: 3, align: 1) { +alloc9 (size: 3, align: 1) { 66 6f 6f │ foo } @@ -44,12 +44,12 @@ alloc10 (size: 3, align: 1) { 62 61 72 │ bar } -alloc14 (size: 24, align: 4) { - 0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼.... +alloc13 (size: 24, align: 4) { + 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼.... 0x10 │ ╾─alloc16─╼ 04 00 00 00 │ ╾──╼.... } -alloc13 (size: 3, align: 1) { +alloc14 (size: 3, align: 1) { 6d 65 68 │ meh } From 134a5aea52641715dd1ea1e4ad0e6a5693fbedc6 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Thu, 2 Feb 2023 16:10:43 -0800 Subject: [PATCH 073/137] Add a linker argument back to boostrap.py In https://github.com/rust-lang/rust/pull/101783 I accidentally removed a load-bearing linker argument. This PR adds it back in. --- src/bootstrap/bootstrap.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2d5018d934e2..9cf43fc7a219 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -753,6 +753,9 @@ class RustBuild(object): target_features += ["-crt-static"] if target_features: env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features)) + target_linker = self.get_toml("linker", build_section) + if target_linker is not None: + env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros" if self.get_toml("deny-warnings", "rust") != "false": From f29000eba9ebd43dca5ae97bab39148cce9319bc Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 3 Feb 2023 10:04:15 +0100 Subject: [PATCH 074/137] Use new helper inside probe --- compiler/rustc_trait_selection/src/solve/project_goals.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 170b560d7b6a..9f62f686af64 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -587,12 +587,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx()); - let nested_goals = ecx.infcx.eq( - goal.param_env, - goal.predicate.term.ty().expect("expected ty goal"), - discriminant, - )?; - ecx.evaluate_all_and_make_canonical_response(nested_goals) + ecx.infcx + .probe(|_| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant)) } } From b83078fd7108972ce56263278a515d62e5f35ee2 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 3 Feb 2023 10:42:37 +0000 Subject: [PATCH 075/137] loudly tell people when `Cargo.lock` changes --- triagebot.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 79958729fc52..cc8221e5cd8d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -459,6 +459,14 @@ These commits modify **compiler targets**. [mentions."src/doc/style-guide"] cc = ["@rust-lang/style"] +[mentions."Cargo.lock"] +message = """ +These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs. +This was probably unintentional and should be reverted before this PR is merged. + +If this was intentional then you can ignore this comment. +""" + [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" From f874f6768caa8b59b99feffc708e868328129fd5 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 3 Feb 2023 11:10:24 +0000 Subject: [PATCH 076/137] Fix suggestion for coercing Option<&String> to Option<&str> --- .../locales/en-US/hir_typeck.ftl | 2 + .../src/fn_ctxt/suggestions.rs | 13 +++-- tests/ui/typeck/issue-89856.fixed | 18 +++++++ tests/ui/typeck/issue-89856.rs | 14 ++++- tests/ui/typeck/issue-89856.stderr | 54 ++++++++++++++++--- 5 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 tests/ui/typeck/issue-89856.fixed diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl index 0f13d29d0fcb..05ac8db0db88 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl @@ -61,3 +61,5 @@ hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang ite hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide + +hir_typeck_convert_to_str = try converting the passed type into a `&str` diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6046e55c65c1..3f433a0928c5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3,7 +3,7 @@ use super::FnCtxt; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; -use rustc_errors::{Applicability, Diagnostic, MultiSpan}; +use rustc_errors::{fluent, Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; @@ -414,11 +414,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(adt, _) = peeled.kind() && Some(adt.did()) == self.tcx.lang_items().string() { + let sugg = if ref_cnt == 0 { + ".as_deref()" + } else { + ".map(|x| x.as_str())" + }; err.span_suggestion_verbose( expr.span.shrink_to_hi(), - "try converting the passed type into a `&str`", - format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)), - Applicability::MaybeIncorrect, + fluent::hir_typeck_convert_to_str, + sugg, + Applicability::MachineApplicable, ); return true; } diff --git a/tests/ui/typeck/issue-89856.fixed b/tests/ui/typeck/issue-89856.fixed new file mode 100644 index 000000000000..3e1a006efa06 --- /dev/null +++ b/tests/ui/typeck/issue-89856.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +fn take_str_maybe(_: Option<&str>) { } +fn main() { + let string = String::from("Hello, world"); + + let option: Option = Some(string.clone()); + take_str_maybe(option.as_deref()); + //~^ ERROR: mismatched types [E0308] + + let option_ref = Some(&string); + take_str_maybe(option_ref.map(|x| x.as_str())); + //~^ ERROR: mismatched types [E0308] + + let option_ref_ref = option_ref.as_ref(); + take_str_maybe(option_ref_ref.map(|x| x.as_str())); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-89856.rs b/tests/ui/typeck/issue-89856.rs index b021e349e358..cfe6e19b303f 100644 --- a/tests/ui/typeck/issue-89856.rs +++ b/tests/ui/typeck/issue-89856.rs @@ -1,8 +1,18 @@ -fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } +// run-rustfix +fn take_str_maybe(_: Option<&str>) { } fn main() { let string = String::from("Hello, world"); - let option = Some(&string); + + let option: Option = Some(string.clone()); take_str_maybe(option); //~^ ERROR: mismatched types [E0308] + + let option_ref = Some(&string); + take_str_maybe(option_ref); + //~^ ERROR: mismatched types [E0308] + + let option_ref_ref = option_ref.as_ref(); + take_str_maybe(option_ref_ref); + //~^ ERROR: mismatched types [E0308] } diff --git a/tests/ui/typeck/issue-89856.stderr b/tests/ui/typeck/issue-89856.stderr index 6b9cbe52c255..bd76f1724682 100644 --- a/tests/ui/typeck/issue-89856.stderr +++ b/tests/ui/typeck/issue-89856.stderr @@ -1,23 +1,63 @@ error[E0308]: mismatched types - --> $DIR/issue-89856.rs:6:20 + --> $DIR/issue-89856.rs:8:20 | LL | take_str_maybe(option); - | -------------- ^^^^^^ expected `Option<&str>`, found `Option<&String>` + | -------------- ^^^^^^ expected `Option<&str>`, found `Option` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&str>` + found enum `Option` +note: function defined here + --> $DIR/issue-89856.rs:3:4 + | +LL | fn take_str_maybe(_: Option<&str>) { } + | ^^^^^^^^^^^^^^ --------------- +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option.as_deref()); + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:12:20 + | +LL | take_str_maybe(option_ref); + | -------------- ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>` | | | arguments to this function are incorrect | = note: expected enum `Option<&str>` found enum `Option<&String>` note: function defined here - --> $DIR/issue-89856.rs:1:4 + --> $DIR/issue-89856.rs:3:4 | -LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } +LL | fn take_str_maybe(_: Option<&str>) { } | ^^^^^^^^^^^^^^ --------------- help: try converting the passed type into a `&str` | -LL | take_str_maybe(option.map(|x| &**x)); - | ++++++++++++++ +LL | take_str_maybe(option_ref.map(|x| x.as_str())); + | ++++++++++++++++++++ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:16:20 + | +LL | take_str_maybe(option_ref_ref); + | -------------- ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&str>` + found enum `Option<&&String>` +note: function defined here + --> $DIR/issue-89856.rs:3:4 + | +LL | fn take_str_maybe(_: Option<&str>) { } + | ^^^^^^^^^^^^^^ --------------- +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option_ref_ref.map(|x| x.as_str())); + | ++++++++++++++++++++ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. From b886a4de157873c6a3e536a517fd6b097a4ab11b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Feb 2023 05:56:04 +0000 Subject: [PATCH 077/137] Replace `ConstFnMutClosure` with const closures --- library/core/src/cmp.rs | 13 +--- library/core/src/const_closure.rs | 78 ------------------- .../core/src/iter/adapters/array_chunks.rs | 6 +- .../core/src/iter/adapters/by_ref_sized.rs | 19 ++--- library/core/src/iter/mod.rs | 6 +- library/core/src/lib.rs | 2 - library/core/src/ops/try_trait.rs | 17 ++-- 7 files changed, 21 insertions(+), 120 deletions(-) delete mode 100644 library/core/src/const_closure.rs diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b75ae996e485..f290e5baf9dd 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,7 +22,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; use self::Ordering::*; @@ -1291,17 +1290,7 @@ where F: ~const Destruct, K: ~const Destruct, { - const fn imp K, K: ~const Ord>( - f: &mut F, - (v1, v2): (&T, &T), - ) -> Ordering - where - T: ~const Destruct, - K: ~const Destruct, - { - f(v1).cmp(&f(v2)) - } - max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) + max_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2))) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs deleted file mode 100644 index 97900a4862f5..000000000000 --- a/library/core/src/const_closure.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::marker::Destruct; -use crate::marker::Tuple; - -/// Struct representing a closure with mutably borrowed data. -/// -/// Example: -/// ```no_build -/// #![feature(const_mut_refs)] -/// use crate::const_closure::ConstFnMutClosure; -/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 { -/// *state += arg; -/// *state -/// } -/// let mut i = 5; -/// let mut cl = ConstFnMutClosure::new(&mut i, imp); -/// -/// assert!(7 == cl(2)); -/// assert!(8 == cl(1)); -/// ``` -pub(crate) struct ConstFnMutClosure { - /// The Data captured by the Closure. - /// Must be either a (mutable) reference or a tuple of (mutable) references. - pub data: CapturedData, - /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn - pub func: Function, -} -impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> { - /// Function for creating a new closure. - /// - /// `data` is the a mutable borrow of data that is captured from the environment. - /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually. - /// - /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure - /// and return the return value of the closure. - pub(crate) const fn new( - data: &'a mut CapturedData, - func: Function, - ) -> Self - where - Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, - { - Self { data, func } - } -} - -macro_rules! impl_fn_mut_tuple { - ($($var:ident)*) => { - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnOnce for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct, - { - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } - } - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnMut for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, - { - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - #[allow(non_snake_case)] - let ($($var),*) = &mut self.data; - (self.func)(($($var),*), args) - } - } - }; -} -impl_fn_mut_tuple!(A); -impl_fn_mut_tuple!(A B); -impl_fn_mut_tuple!(A B C); -impl_fn_mut_tuple!(A B C D); -impl_fn_mut_tuple!(A B C D E); diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 5e4211058aa6..af786609757b 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,5 +1,4 @@ use crate::array; -use crate::const_closure::ConstFnMutClosure; use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce}; use crate::mem::{self, MaybeUninit}; use crate::ops::{ControlFlow, NeverShortCircuit, Try}; @@ -189,13 +188,12 @@ where I: Iterator, { #[inline] - default fn fold(mut self, init: B, mut f: F) -> B + default fn fold(mut self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp); - self.try_fold(init, fold).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 1945e402ff50..477e7117c3ea 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,7 +1,4 @@ -use crate::{ - const_closure::ConstFnMutClosure, - ops::{NeverShortCircuit, Try}, -}; +use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -39,13 +36,12 @@ impl Iterator for ByRefSized<'_, I> { } #[inline] - fn fold(self, init: B, mut f: F) -> B + fn fold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) - .0 + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -76,17 +72,12 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn rfold(self, init: B, mut f: F) -> B + fn rfold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold( - self.0, - init, - ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp), - ) - .0 + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index bb35d50b4bfd..00f57fbcc616 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -362,15 +362,13 @@ macro_rules! impl_fold_via_try_fold { }; (@internal $fold:ident -> $try_fold:ident) => { #[inline] - fn $fold(mut self, init: AAA, mut fold: FFF) -> AAA + fn $fold(mut self, init: AAA, fold: FFF) -> AAA where FFF: FnMut(AAA, Self::Item) -> AAA, { - use crate::const_closure::ConstFnMutClosure; use crate::ops::NeverShortCircuit; - let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp); - self.$try_fold(init, fold).0 + self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 } }; } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 8961ef4ab481..dc0702c467a4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -376,8 +376,6 @@ mod bool; mod tuple; mod unit; -mod const_closure; - #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 84a69046807c..9108fc630452 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -379,13 +379,18 @@ pub(crate) type ChangeOutputType = <::Residual as Residual>:: pub(crate) struct NeverShortCircuit(pub T); impl NeverShortCircuit { - /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`. #[inline] - pub const fn wrap_mut_2_imp T>( - f: &mut F, - (a, b): (A, B), - ) -> NeverShortCircuit { - NeverShortCircuit(f(a, b)) + pub fn wrap_mut_2( + mut f: impl ~const FnMut(A, B) -> T, + ) -> impl ~const FnMut(A, B) -> Self { + cfg_if! { + if #[cfg(bootstrap)] { + #[allow(unused_parens)] + (const move |a, b| NeverShortCircuit(f(a, b))) + } else { + const move |a, b| NeverShortCircuit(f(a, b)) + } + } } } From 784665d4ce59c5239791f1f96fa2137e47ca1817 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 2 Feb 2023 15:10:41 -0700 Subject: [PATCH 078/137] Replace nbsp in all rustdoc code blocks Co-Authored-By: David Tolnay --- src/librustdoc/html/format.rs | 20 +++++++++---------- src/librustdoc/html/render/print_item.rs | 4 ++-- src/librustdoc/html/static/css/rustdoc.css | 2 ++ .../doc-notable_trait.some-struct-new.html | 2 +- tests/rustdoc/doc-notable_trait.wrap-me.html | 2 +- .../whitespace-after-where-clause.enum2.html | 2 +- ...whitespace-after-where-clause.struct2.html | 2 +- .../whitespace-after-where-clause.union2.html | 2 +- 8 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 33404a768359..74cdf9b9b798 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -208,7 +208,7 @@ impl clean::GenericParamDef { if f.alternate() { write!(f, ": {:#}", print_generic_bounds(bounds, cx))?; } else { - write!(f, ": {}", print_generic_bounds(bounds, cx))?; + write!(f, ": {}", print_generic_bounds(bounds, cx))?; } } @@ -216,7 +216,7 @@ impl clean::GenericParamDef { if f.alternate() { write!(f, " = {:#}", ty.print(cx))?; } else { - write!(f, " = {}", ty.print(cx))?; + write!(f, " = {}", ty.print(cx))?; } } @@ -226,14 +226,14 @@ impl clean::GenericParamDef { if f.alternate() { write!(f, "const {}: {:#}", self.name, ty.print(cx))?; } else { - write!(f, "const {}: {}", self.name, ty.print(cx))?; + write!(f, "const {}: {}", self.name, ty.print(cx))?; } if let Some(default) = default { if f.alternate() { write!(f, " = {:#}", default)?; } else { - write!(f, " = {}", default)?; + write!(f, " = {}", default)?; } } @@ -354,12 +354,12 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( let mut br_with_padding = String::with_capacity(6 * indent + 28); br_with_padding.push_str("
"); for _ in 0..indent + 4 { - br_with_padding.push_str(" "); + br_with_padding.push_str(" "); } let where_preds = where_preds.to_string().replace("
", &br_with_padding); if ending == Ending::Newline { - let mut clause = " ".repeat(indent.saturating_sub(1)); + let mut clause = " ".repeat(indent.saturating_sub(1)); write!(clause, "where{where_preds},")?; clause } else { @@ -368,7 +368,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( format!("
where{where_preds}") } else { let mut clause = br_with_padding; - clause.truncate(clause.len() - 4 * " ".len()); + clause.truncate(clause.len() - 4); write!(clause, "where{where_preds}")?; clause } @@ -1391,8 +1391,8 @@ impl clean::FnDecl { let declaration_len = header_len + args_plain.len() + arrow_plain.len(); let output = if declaration_len > 80 { - let full_pad = format!("
{}", " ".repeat(indent + 4)); - let close_pad = format!("
{}", " ".repeat(indent)); + let full_pad = format!("
{}", " ".repeat(indent + 4)); + let close_pad = format!("
{}", " ".repeat(indent)); format!( "({pad}{args}{close}){arrow}", pad = if self.inputs.values.is_empty() { "" } else { &full_pad }, @@ -1611,7 +1611,7 @@ impl clean::TypeBinding { if f.alternate() { write!(f, ": {:#}", print_generic_bounds(bounds, cx))?; } else { - write!(f, ": {}", print_generic_bounds(bounds, cx))?; + write!(f, ": {}", print_generic_bounds(bounds, cx))?; } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index bd7548003ad3..9a7a08ab8068 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1157,7 +1157,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) { for (i, ty) in s.iter().enumerate() { if i > 0 { - w.write_str(", "); + w.write_str(", "); } match *ty.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"), @@ -1297,7 +1297,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: "
\ \ §\ - {f}: {t}\ + {f}: {t}\ ", id = id, f = field.name.unwrap(), diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ee988090ca33..a1e91118303c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -184,6 +184,7 @@ h4.code-header { font-weight: 600; margin: 0; padding: 0; + white-space: pre-wrap; } #crate-search, @@ -642,6 +643,7 @@ pre, .rustdoc.source .example-wrap { .fn .where, .where.fmt-newline { display: block; + white-space: pre-wrap; font-size: 0.875rem; } diff --git a/tests/rustdoc/doc-notable_trait.some-struct-new.html b/tests/rustdoc/doc-notable_trait.some-struct-new.html index 384be6689540..e8f4f6000457 100644 --- a/tests/rustdoc/doc-notable_trait.some-struct-new.html +++ b/tests/rustdoc/doc-notable_trait.some-struct-new.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/doc-notable_trait.wrap-me.html b/tests/rustdoc/doc-notable_trait.wrap-me.html index 0cc1ee10fd33..e7909669b150 100644 --- a/tests/rustdoc/doc-notable_trait.wrap-me.html +++ b/tests/rustdoc/doc-notable_trait.wrap-me.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.enum2.html b/tests/rustdoc/whitespace-after-where-clause.enum2.html index 7bc9b780197b..065ce757de1a 100644 --- a/tests/rustdoc/whitespace-after-where-clause.enum2.html +++ b/tests/rustdoc/whitespace-after-where-clause.enum2.html @@ -1,4 +1,4 @@ -
pub enum Cow2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub enum Cow2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     Borrowed(&'a B),
     Whatever(u32),
 }
\ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.struct2.html b/tests/rustdoc/whitespace-after-where-clause.struct2.html index d872d516c094..c647e8d71218 100644 --- a/tests/rustdoc/whitespace-after-where-clause.struct2.html +++ b/tests/rustdoc/whitespace-after-where-clause.struct2.html @@ -1,4 +1,4 @@ -
pub struct Struct2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub struct Struct2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     pub a: &'a B,
     pub b: u32,
 }
\ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html index fc78e9b6039b..66ad30c92001 100644 --- a/tests/rustdoc/whitespace-after-where-clause.union2.html +++ b/tests/rustdoc/whitespace-after-where-clause.union2.html @@ -1,3 +1,3 @@ -
pub union Union2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub union Union2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     /* private fields */
 }
\ No newline at end of file From cb55d10eb2b11ea6aee96c111b0996519af1fdf5 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 29 Oct 2022 21:14:02 +0800 Subject: [PATCH 079/137] Fix #103320, add explanatory message for [#must_use] --- .../locales/en-US/borrowck.ftl | 2 +- .../locales/en-US/lint.ftl | 1 + compiler/rustc_lint/src/lints.rs | 18 +++++ compiler/rustc_lint/src/unused.rs | 18 ++++- library/core/src/ops/arith.rs | 18 +++-- .../lint/unused/issue-103320-must-use-ops.rs | 27 ++++++++ .../unused/issue-103320-must-use-ops.stderr | 67 +++++++++++++++++++ 7 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 tests/ui/lint/unused/issue-103320-must-use-ops.rs create mode 100644 tests/ui/lint/unused/issue-103320-must-use-ops.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 0021638c1026..fe77cf23e8f9 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -33,7 +33,7 @@ borrowck_var_here_defined = variable defined here borrowck_var_here_captured = variable captured here -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure +borrowck_closure_inferred_mut = inferred to be a `FnMut` closure borrowck_returned_closure_escaped = returns a closure that contains a reference to a captured variable, which then escapes the closure body diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index dca678dff7a7..b1e7cc69a809 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -309,6 +309,7 @@ lint_unused_generator = .note = generators are lazy and do nothing unless resumed lint_unused_def = unused {$pre}`{$def}`{$post} that must be used + .suggestion = use `let _ = ...` to ignore the resulting value lint_path_statement_drop = path statement drops value .suggestion = use `drop` to clarify the intent diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0c1019545f38..2e447b900e11 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1402,6 +1402,21 @@ pub struct UnusedDef<'a, 'b> { pub cx: &'a LateContext<'b>, pub def_id: DefId, pub note: Option, + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +pub enum UnusedDefSuggestion { + #[suggestion( + suggestion, + style = "verbose", + code = "let _ = ", + applicability = "machine-applicable" + )] + Default { + #[primary_span] + span: Span, + }, } // Needed because of def_path_str @@ -1417,6 +1432,9 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { if let Some(note) = self.note { diag.note(note.as_str()); } + if let Some(sugg) = self.suggestion { + diag.subdiagnostic(sugg); + } diag } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 4c9b3df2dbd3..622601224ff9 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,7 +1,7 @@ use crate::lints::{ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, - UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion, - UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, + UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim, + UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, }; use crate::Lint; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -418,6 +418,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { + let suggestion = if matches!( + cx.tcx.get_diagnostic_name(*def_id), + Some(sym::add) + | Some(sym::sub) + | Some(sym::mul) + | Some(sym::div) + | Some(sym::rem) + | Some(sym::neg), + ) { + Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() }) + } else { + None + }; cx.emit_spanned_lint( UNUSED_MUST_USE, *span, @@ -427,6 +440,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, + suggestion, }, ); } diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index cc13db5c9565..0c7ee9630c6e 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -86,7 +86,8 @@ pub trait Add { /// ``` /// assert_eq!(12 + 1, 13); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "add"] #[stable(feature = "rust1", since = "1.0.0")] fn add(self, rhs: Rhs) -> Self::Output; } @@ -195,7 +196,8 @@ pub trait Sub { /// ``` /// assert_eq!(12 - 1, 11); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "sub"] #[stable(feature = "rust1", since = "1.0.0")] fn sub(self, rhs: Rhs) -> Self::Output; } @@ -325,7 +327,8 @@ pub trait Mul { /// ``` /// assert_eq!(12 * 2, 24); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "mul"] #[stable(feature = "rust1", since = "1.0.0")] fn mul(self, rhs: Rhs) -> Self::Output; } @@ -459,7 +462,8 @@ pub trait Div { /// ``` /// assert_eq!(12 / 2, 6); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "div"] #[stable(feature = "rust1", since = "1.0.0")] fn div(self, rhs: Rhs) -> Self::Output; } @@ -562,7 +566,8 @@ pub trait Rem { /// ``` /// assert_eq!(12 % 10, 2); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "rem"] #[stable(feature = "rust1", since = "1.0.0")] fn rem(self, rhs: Rhs) -> Self::Output; } @@ -678,7 +683,8 @@ pub trait Neg { /// let x: i32 = 12; /// assert_eq!(-x, -12); /// ``` - #[must_use] + #[must_use = "this returns the result of the operation, without modifying the original"] + #[rustc_diagnostic_item = "neg"] #[stable(feature = "rust1", since = "1.0.0")] fn neg(self) -> Self::Output; } diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.rs b/tests/ui/lint/unused/issue-103320-must-use-ops.rs new file mode 100644 index 000000000000..597d312fa5ec --- /dev/null +++ b/tests/ui/lint/unused/issue-103320-must-use-ops.rs @@ -0,0 +1,27 @@ +// check-pass + +#![warn(unused_must_use)] +#![feature(never_type)] + +use std::ops::Add; +use std::ops::Sub; +use std::ops::Mul; +use std::ops::Div; +use std::ops::Rem; + +fn main() { + let x = 2_u32; + (x.add(4), x.sub(4), x.mul(4), x.div(4), x.rem(4)); + + x.add(4); //~ WARN unused return value of `add` that must be used + + x.sub(4); //~ WARN unused return value of `sub` that must be used + + x.mul(4); //~ WARN unused return value of `mul` that must be used + + x.div(4); //~ WARN unused return value of `div` that must be used + + x.rem(4); //~ WARN unused return value of `rem` that must be used + + println!("{}", x); +} diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.stderr b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr new file mode 100644 index 000000000000..57439ec6a8fd --- /dev/null +++ b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr @@ -0,0 +1,67 @@ +warning: unused return value of `add` that must be used + --> $DIR/issue-103320-must-use-ops.rs:16:5 + | +LL | x.add(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +note: the lint level is defined here + --> $DIR/issue-103320-must-use-ops.rs:3:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.add(4); + | +++++++ + +warning: unused return value of `sub` that must be used + --> $DIR/issue-103320-must-use-ops.rs:18:5 + | +LL | x.sub(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.sub(4); + | +++++++ + +warning: unused return value of `mul` that must be used + --> $DIR/issue-103320-must-use-ops.rs:20:5 + | +LL | x.mul(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.mul(4); + | +++++++ + +warning: unused return value of `div` that must be used + --> $DIR/issue-103320-must-use-ops.rs:22:5 + | +LL | x.div(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.div(4); + | +++++++ + +warning: unused return value of `rem` that must be used + --> $DIR/issue-103320-must-use-ops.rs:24:5 + | +LL | x.rem(4); + | ^^^^^^^^ + | + = note: this returns the result of the operation, without modifying the original +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = x.rem(4); + | +++++++ + +warning: 5 warnings emitted + From 9e1c600f74f966ec583f0ac39d0c2a103a2560a7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 18 Jan 2023 22:43:05 -0800 Subject: [PATCH 080/137] Disallow impl autotrait for trait object --- compiler/rustc_data_structures/src/sync.rs | 4 +- .../src/coherence/orphan.rs | 201 ++++++++++++++---- ...ce-impl-trait-for-marker-trait-negative.rs | 23 +- ...mpl-trait-for-marker-trait-negative.stderr | 44 +++- ...ce-impl-trait-for-marker-trait-positive.rs | 23 +- ...mpl-trait-for-marker-trait-positive.stderr | 44 +++- 6 files changed, 269 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index ed5341c40ef0..ad71dcdf9d95 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -31,8 +31,8 @@ cfg_if! { pub auto trait Send {} pub auto trait Sync {} - impl Send for T {} - impl Sync for T {} + impl Send for T {} + impl Sync for T {} #[macro_export] macro_rules! rustc_erase_owner { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 95b03eb8263f..5c478b96fe6b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IgnoreRegions; use rustc_middle::ty::{ - self, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_session::lint; use rustc_span::def_id::{DefId, LocalDefId}; @@ -86,7 +86,7 @@ fn do_orphan_check_impl<'tcx>( // struct B { } // impl Foo for A { } // impl Foo for B { } - // impl !Send for (A, B) { } + // impl !Foo for (A, B) { } // ``` // // This final impl is legal according to the orphan @@ -99,50 +99,171 @@ fn do_orphan_check_impl<'tcx>( tcx.trait_is_auto(trait_def_id) ); - if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() { + if tcx.trait_is_auto(trait_def_id) { let self_ty = trait_ref.self_ty(); - let opt_self_def_id = match *self_ty.kind() { - ty::Adt(self_def, _) => Some(self_def.did()), - ty::Foreign(did) => Some(did), - _ => None, + + // If the impl is in the same crate as the auto-trait, almost anything + // goes. + // + // impl MyAuto for Rc {} // okay + // impl !MyAuto for *const T {} // okay + // impl MyAuto for T {} // okay + // + // But there is one important exception: implementing for a trait object + // is not allowed. + // + // impl MyAuto for dyn Trait {} // NOT OKAY + // impl MyAuto for T {} // NOT OKAY + // + enum LocalImpl { + Allow, + Disallow { problematic_kind: &'static str }, + } + + // If the auto-trait is from a dependency, it must only be getting + // implemented for a nominal type, and specifically one local to the + // current crate. + // + // impl Sync for MyStruct {} // okay + // + // impl Sync for Rc {} // NOT OKAY + enum NonlocalImpl { + Allow, + DisallowBecauseNonlocal, + DisallowOther, + } + + // Exhaustive match considering that this logic is essential for + // soundness. + let (local_impl, nonlocal_impl) = match self_ty.kind() { + // struct Struct; + // impl AutoTrait for Struct {} + ty::Adt(self_def, _) => ( + LocalImpl::Allow, + if self_def.did().is_local() { + NonlocalImpl::Allow + } else { + NonlocalImpl::DisallowBecauseNonlocal + }, + ), + + // extern { type OpaqueType; } + // impl AutoTrait for OpaqueType {} + ty::Foreign(did) => ( + LocalImpl::Allow, + if did.is_local() { + NonlocalImpl::Allow + } else { + NonlocalImpl::DisallowBecauseNonlocal + }, + ), + + // impl AutoTrait for dyn Trait {} + ty::Dynamic(..) => ( + LocalImpl::Disallow { problematic_kind: "trait object" }, + NonlocalImpl::DisallowOther, + ), + + // impl AutoTrait for T {} + // impl AutoTrait for T {} + ty::Param(..) => ( + if self_ty.is_sized(tcx, tcx.param_env(def_id)) { + LocalImpl::Allow + } else { + LocalImpl::Disallow { problematic_kind: "generic type" } + }, + NonlocalImpl::DisallowOther, + ), + + // trait Id { type This: ?Sized; } + // impl Id for T { + // type This = T; + // } + // impl AutoTrait for ::This {} + ty::Alias(AliasKind::Projection, _) => ( + LocalImpl::Disallow { problematic_kind: "associated type" }, + NonlocalImpl::DisallowOther, + ), + + // type Opaque = impl Trait; + // impl AutoTrait for Opaque {} + ty::Alias(AliasKind::Opaque, _) => ( + LocalImpl::Disallow { problematic_kind: "opaque type" }, + NonlocalImpl::DisallowOther, + ), + + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Str + | ty::Array(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Never + | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), + + ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) => span_bug!(sp, "weird self type for autotrait impl"), + + ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow), }; - let msg = match opt_self_def_id { - // We only want to permit nominal types, but not *all* nominal types. - // They must be local to the current crate, so that people - // can't do `unsafe impl Send for Rc` or - // `impl !Send for Box`. - Some(self_def_id) => { - if self_def_id.is_local() { - None - } else { - Some(( - format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - tcx.def_path_str(trait_def_id) - ), - "can't implement cross-crate trait for type in another crate", - )) + if trait_def_id.is_local() { + match local_impl { + LocalImpl::Allow => {} + LocalImpl::Disallow { problematic_kind } => { + let msg = format!( + "traits with a default impl, like `{trait}`, \ + cannot be implemented for {problematic_kind} `{self_ty}`", + trait = tcx.def_path_str(trait_def_id), + ); + let label = format!( + "a trait object implements `{trait}` if and only if `{trait}` \ + is one of the trait object's trait bounds", + trait = tcx.def_path_str(trait_def_id), + ); + let reported = + struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit(); + return Err(reported); } } - _ => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, can \ + } else { + if let Some((msg, label)) = match nonlocal_impl { + NonlocalImpl::Allow => None, + NonlocalImpl::DisallowBecauseNonlocal => Some(( + format!( + "cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + tcx.def_path_str(trait_def_id) + ), + "can't implement cross-crate trait for type in another crate", + )), + NonlocalImpl::DisallowOther => Some(( + format!( + "cross-crate traits with a default impl, like `{}`, can \ only be implemented for a struct/enum type, not `{}`", - tcx.def_path_str(trait_def_id), - self_ty - ), - "can't implement cross-crate trait with a default impl for \ - non-struct/enum type", - )), - }; - - if let Some((msg, label)) = msg { - let reported = - struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); - return Err(reported); + tcx.def_path_str(trait_def_id), + self_ty + ), + "can't implement cross-crate trait with a default impl for \ + non-struct/enum type", + )), + } { + let reported = + struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); + return Err(reported); + } } } diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs index 50d9a480ad1e..98f1558b7ffe 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs @@ -12,19 +12,26 @@ auto trait Marker2 {} trait Object: Marker1 {} // A supertrait marker is illegal... -impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371 +impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371 + //~^ ERROR 0321 // ...and also a direct component. -impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371 - -// But implementing a marker if it is not present is OK. -impl !Marker2 for dyn Object {} // OK +impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371 + //~^ ERROR 0321 // A non-principal trait-object type is orphan even in its crate. impl !Send for dyn Marker2 {} //~ ERROR E0117 -// And impl'ing a remote marker for a local trait object is forbidden -// by one of these special orphan-like rules. +// Implementing a marker for a local trait object is forbidden by a special +// orphan-like rule. +impl !Marker2 for dyn Object {} //~ ERROR E0321 impl !Send for dyn Object {} //~ ERROR E0321 impl !Send for dyn Object + Marker2 {} //~ ERROR E0321 -fn main() { } +// Blanket impl that applies to dyn Object is equally problematic. +auto trait Marker3 {} +impl !Marker3 for T {} //~ ERROR E0321 + +auto trait Marker4 {} +impl !Marker4 for T {} // okay + +fn main() {} diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr index c364c707ff9e..ea38afc40ce8 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -1,17 +1,41 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | -LL | impl !Marker1 for dyn Object + Marker2 { } +LL | impl !Marker1 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 | -LL | impl !Marker2 for dyn Object + Marker2 { } +LL | impl !Marker1 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 + | +LL | impl !Marker2 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1 + | +LL | impl !Marker2 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds + +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1 + | +LL | impl !Marker2 for dyn Object {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1 | LL | impl !Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^----------- @@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | impl !Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -error: aborting due to 5 previous errors +error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1 + | +LL | impl !Marker3 for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0117, E0321, E0371. For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs index faac6d983f31..db2e2b4509a2 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs @@ -12,19 +12,26 @@ auto trait Marker2 {} trait Object: Marker1 {} // A supertrait marker is illegal... -impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371 +impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371 + //~^ ERROR E0321 // ...and also a direct component. -impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371 - -// But implementing a marker if it is not present is OK. -impl Marker2 for dyn Object {} // OK +impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371 + //~^ ERROR E0321 // A non-principal trait-object type is orphan even in its crate. unsafe impl Send for dyn Marker2 {} //~ ERROR E0117 -// And impl'ing a remote marker for a local trait object is forbidden -// by one of these special orphan-like rules. +// Implementing a marker for a local trait object is forbidden by a special +// orphan-like rule. +impl Marker2 for dyn Object {} //~ ERROR E0321 unsafe impl Send for dyn Object {} //~ ERROR E0321 unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321 -fn main() { } +// Blanket impl that applies to dyn Object is equally problematic. +auto trait Marker3 {} +impl Marker3 for T {} //~ ERROR E0321 + +auto trait Marker4 {} +impl Marker4 for T {} // okay + +fn main() {} diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr index b80429794f92..2a8713bc3279 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -1,17 +1,41 @@ error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | -LL | impl Marker1 for dyn Object + Marker2 { } +LL | impl Marker1 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` -error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 +error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 | -LL | impl Marker2 for dyn Object + Marker2 { } +LL | impl Marker1 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1 + | +LL | impl Marker2 for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1 + | +LL | impl Marker2 for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds + +error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1 + | +LL | impl Marker2 for dyn Object {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds + error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1 | LL | unsafe impl Send for dyn Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^----------- @@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | unsafe impl Send for dyn Object + Marker2 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -error: aborting due to 5 previous errors +error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1 + | +LL | impl Marker3 for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0117, E0321, E0371. For more information about an error, try `rustc --explain E0117`. From 4501d3abe17a3dc10f0dffcb38be04b58a33bafb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 19 Jan 2023 01:24:45 -0800 Subject: [PATCH 081/137] Autotrait bounds on dyn-safe trait methods --- .../src/coherence/orphan.rs | 22 +++++++ .../src/traits/object_safety.rs | 60 +++++++++++++++---- .../self-in-where-clause-allowed.rs | 23 +++++++ .../self-in-where-clause-allowed.stderr | 15 +++++ 4 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 tests/ui/where-clauses/self-in-where-clause-allowed.rs create mode 100644 tests/ui/where-clauses/self-in-where-clause-allowed.stderr diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 5c478b96fe6b..7d381d8902ac 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -115,6 +115,28 @@ fn do_orphan_check_impl<'tcx>( // impl MyAuto for dyn Trait {} // NOT OKAY // impl MyAuto for T {} // NOT OKAY // + // With this restriction, it's guaranteed that an auto-trait is + // implemented for a trait object if and only if the auto-trait is one + // of the trait object's trait bounds (or a supertrait of a bound). In + // other words `dyn Trait + AutoTrait` always implements AutoTrait, + // while `dyn Trait` never implements AutoTrait. + // + // This is necessary in order for autotrait bounds on methods of trait + // objects to be sound. + // + // auto trait AutoTrait {} + // + // trait ObjectSafeTrait { + // fn f(&self) where Self: AutoTrait; + // } + // + // We can allow f to be called on `dyn ObjectSafeTrait + AutoTrait`. + // + // If we didn't deny `impl AutoTrait for dyn Trait`, it would be unsound + // for the ObjectSafeTrait shown above to be object safe because someone + // could take some type implementing ObjectSafeTrait but not AutoTrait, + // unsize it to `dyn ObjectSafeTrait`, and call .f() which has no + // concrete implementation (issue #50781). enum LocalImpl { Allow, Disallow { problematic_kind: &'static str }, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 565cfca9090e..8f548acfd2ea 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -547,16 +547,56 @@ fn virtual_call_violation_for_method<'tcx>( // NOTE: This check happens last, because it results in a lint, and not a // hard error. - if tcx - .predicates_of(method.def_id) - .predicates - .iter() - // A trait object can't claim to live more than the concrete type, - // so outlives predicates will always hold. - .cloned() - .filter(|(p, _)| p.to_opt_type_outlives().is_none()) - .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred)) - { + if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| { + // dyn Trait is okay: + // + // trait Trait { + // fn f(&self) where Self: 'static; + // } + // + // because a trait object can't claim to live longer than the concrete + // type. If the lifetime bound holds on dyn Trait then it's guaranteed + // to hold as well on the concrete type. + if pred.to_opt_type_outlives().is_some() { + return false; + } + + // dyn Trait is okay: + // + // auto trait AutoTrait {} + // + // trait Trait { + // fn f(&self) where Self: AutoTrait; + // } + // + // because `impl AutoTrait for dyn Trait` is disallowed by coherence. + // Traits with a default impl are implemented for a trait object if and + // only if the autotrait is one of the trait object's trait bounds, like + // in `dyn Trait + AutoTrait`. This guarantees that trait objects only + // implement auto traits if the underlying type does as well. + if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate { + trait_ref: pred_trait_ref, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + })) = pred.kind().skip_binder() + && pred_trait_ref.self_ty() == tcx.types.self_param + && tcx.trait_is_auto(pred_trait_ref.def_id) + { + // Consider bounds like `Self: Bound`. Auto traits are not + // allowed to have generic parameters so `auto trait Bound {}` + // would already have reported an error at the definition of the + // auto trait. + if pred_trait_ref.substs.len() != 1 { + tcx.sess.diagnostic().delay_span_bug( + span, + "auto traits cannot have generic parameters", + ); + } + return false; + } + + contains_illegal_self_type_reference(tcx, trait_def_id, pred.clone()) + }) { return Some(MethodViolationCode::WhereClauseReferencesSelf); } diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.rs b/tests/ui/where-clauses/self-in-where-clause-allowed.rs new file mode 100644 index 000000000000..6cf5ed2e46ae --- /dev/null +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.rs @@ -0,0 +1,23 @@ +// check-fail + +#![feature(auto_traits)] +#![deny(where_clauses_object_safety)] + +auto trait AutoTrait {} + +trait Trait { + fn static_lifetime_bound(&self) where Self: 'static {} + + fn arg_lifetime_bound<'a>(&self, _arg: &'a ()) where Self: 'a {} + + fn autotrait_bound(&self) where Self: AutoTrait {} +} + +impl Trait for () {} + +fn main() { + let trait_object = &() as &dyn Trait; + trait_object.static_lifetime_bound(); + trait_object.arg_lifetime_bound(&()); + trait_object.autotrait_bound(); //~ ERROR: the trait bound `dyn Trait: AutoTrait` is not satisfied +} diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr new file mode 100644 index 000000000000..ea51f5084f87 --- /dev/null +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied + --> $DIR/self-in-where-clause-allowed.rs:22:18 + | +LL | trait_object.autotrait_bound(); + | ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait` + | +note: required by a bound in `Trait::autotrait_bound` + --> $DIR/self-in-where-clause-allowed.rs:13:43 + | +LL | fn autotrait_bound(&self) where Self: AutoTrait {} + | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From da1360d981f272cc1c3aa81b1fa013fff5b2676d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 3 Feb 2023 18:53:27 +0000 Subject: [PATCH 082/137] Provide structured suggestion for binding needing type on E0594 Partially address #45405. --- .../src/diagnostics/mutability_errors.rs | 60 +++++++++++++++++-- ...orrow-mut-base-ptr-in-aliasable-loc.stderr | 8 ++- tests/ui/borrowck/issue-85765.rs | 6 +- tests/ui/borrowck/issue-85765.stderr | 24 +++++--- tests/ui/borrowck/issue-91206.rs | 2 +- tests/ui/borrowck/issue-91206.stderr | 8 ++- tests/ui/borrowck/issue-92015.stderr | 7 ++- tests/ui/issues/issue-51515.rs | 1 + tests/ui/issues/issue-51515.stderr | 9 ++- 9 files changed, 95 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 40f518b33cfb..cf3240226fb3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -606,12 +606,60 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } Some((false, err_label_span, message)) => { - err.span_label( - err_label_span, - &format!( - "consider changing this binding's type to be: `{message}`" - ), - ); + struct V { + span: Span, + hir_id: Option, + } + + impl<'tcx> Visitor<'tcx> for V { + fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { + if let hir::StmtKind::Local(local) = s.kind { + if local.pat.span == self.span { + self.hir_id = Some(local.hir_id); + } + } + hir::intravisit::walk_stmt(self, s); + } + } + let hir_map = self.infcx.tcx.hir(); + let pat = loop { + // Poor man's try block + let def_id = self.body.source.def_id(); + let hir_id = + hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap()); + let node = hir_map.find(hir_id); + let Some(hir::Node::Item(item)) = node else { break None; }; + let hir::ItemKind::Fn(.., body_id) = item.kind else { break None; }; + let body = self.infcx.tcx.hir().body(body_id); + let mut v = V { span: err_label_span, hir_id: None }; + v.visit_body(body); + break v.hir_id; + }; + if let Some(hir_id) = pat + && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) + { + let (changing, span, sugg) = match local.ty { + Some(ty) => ("changing", ty.span, message), + None => ( + "specifying", + local.pat.span.shrink_to_hi(), + format!(": {message}"), + ), + }; + err.span_suggestion_verbose( + span, + &format!("consider {changing} this binding's type"), + sugg, + Applicability::HasPlaceholders, + ); + } else { + err.span_label( + err_label_span, + &format!( + "consider changing this binding's type to be: `{message}`" + ), + ); + } } None => {} } diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index ce9f7aa050a0..dd0817ff2331 100644 --- a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `**t1`, which is behind a `&` reference --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5 | -LL | let t1 = t0; - | -- consider changing this binding's type to be: `&mut &mut isize` -LL | let p: &isize = &**t0; LL | **t1 = 22; | ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let t1: &mut &mut isize = t0; + | +++++++++++++++++ error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21 diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index 1598cd5d3c86..76e0b5173541 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -1,7 +1,7 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -15,14 +15,14 @@ fn main() { #[rustfmt::skip] let x: &usize = &mut{0}; - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *x = 1; //~^ ERROR cannot assign to `*x`, which is behind a `&` reference //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written #[rustfmt::skip] let y: &usize = &mut(0); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *y = 1; //~^ ERROR cannot assign to `*y`, which is behind a `&` reference //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 7da7dba68ab7..b4bb128cbb42 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference --> $DIR/issue-85765.rs:5:5 | -LL | let rofl: &Vec> = &mut test; - | ---- consider changing this binding's type to be: `&mut Vec>` -LL | LL | rofl.push(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this binding's type + | +LL | let rofl: &mut Vec> = &mut test; + | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference --> $DIR/issue-85765.rs:12:5 @@ -21,20 +23,24 @@ LL | let r = &mut mutvar; error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-85765.rs:19:5 | -LL | let x: &usize = &mut{0}; - | - consider changing this binding's type to be: `&mut usize` -LL | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this binding's type + | +LL | let x: &mut usize = &mut{0}; + | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference --> $DIR/issue-85765.rs:26:5 | -LL | let y: &usize = &mut(0); - | - consider changing this binding's type to be: `&mut usize` -LL | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this binding's type + | +LL | let y: &mut usize = &mut(0); + | ~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index 67407c1eae3c..e062a253767d 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -9,7 +9,7 @@ impl TestClient { fn main() { let client = TestClient; let inner = client.get_inner_ref(); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider specifying this binding's type inner.clear(); //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index 12d8d27c5f02..6653d497873e 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference --> $DIR/issue-91206.rs:13:5 | -LL | let inner = client.get_inner_ref(); - | ----- consider changing this binding's type to be: `&mut Vec` -LL | LL | inner.clear(); | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider specifying this binding's type + | +LL | let inner: &mut Vec = client.get_inner_ref(); + | +++++++++++++++++ error: aborting due to previous error diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr index 62b1183e71b4..ea4f9abb87d9 100644 --- a/tests/ui/borrowck/issue-92015.stderr +++ b/tests/ui/borrowck/issue-92015.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/issue-92015.rs:6:5 | -LL | let foo = Some(&0).unwrap(); - | --- consider changing this binding's type to be: `&mut i32` LL | *foo = 1; | ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let foo: &mut i32 = Some(&0).unwrap(); + | ++++++++++ error: aborting due to previous error diff --git a/tests/ui/issues/issue-51515.rs b/tests/ui/issues/issue-51515.rs index 797c1085d517..84e09afac0a2 100644 --- a/tests/ui/issues/issue-51515.rs +++ b/tests/ui/issues/issue-51515.rs @@ -5,6 +5,7 @@ fn main() { *foo = 32; //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference let bar = foo; + //~^ HELP consider specifying this binding's type *bar = 64; //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference } diff --git a/tests/ui/issues/issue-51515.stderr b/tests/ui/issues/issue-51515.stderr index c4e61e719539..94e5c9f1b832 100644 --- a/tests/ui/issues/issue-51515.stderr +++ b/tests/ui/issues/issue-51515.stderr @@ -10,12 +10,15 @@ LL | let foo = &mut 16; | ~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference - --> $DIR/issue-51515.rs:8:5 + --> $DIR/issue-51515.rs:9:5 | -LL | let bar = foo; - | --- consider changing this binding's type to be: `&mut i32` LL | *bar = 64; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let bar: &mut i32 = foo; + | ++++++++++ error: aborting due to 2 previous errors From c2b65ffe295bf98cb1140ddb5f82efdb0f6f33ce Mon Sep 17 00:00:00 2001 From: Ame <104745335+ameknite@users.noreply.github.com> Date: Fri, 3 Feb 2023 04:54:27 -0600 Subject: [PATCH 083/137] Clarifying that .map() returns None if None. --- library/core/src/option.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c43b728022d2..f485763b2342 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -943,7 +943,7 @@ impl Option { // Transforming contained values ///////////////////////////////////////////////////////////////////////// - /// Maps an `Option` to `Option` by applying a function to a contained value. + /// Maps an `Option` to `Option` by applying a function to a contained value (if `Some`) or return `None` (if `None`). /// /// # Examples /// @@ -955,8 +955,10 @@ impl Option { /// let maybe_some_string = Some(String::from("Hello, World!")); /// // `Option::map` takes self *by value*, consuming `maybe_some_string` /// let maybe_some_len = maybe_some_string.map(|s| s.len()); - /// /// assert_eq!(maybe_some_len, Some(13)); + /// + /// let x: Option<&str> = None; + /// assert_eq!(x.map(|s| s.len()), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] From b384692f4c7fa61b36f9314d6e597154914f4957 Mon Sep 17 00:00:00 2001 From: Ame <104745335+ameknite@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:41:59 -0600 Subject: [PATCH 084/137] nit fixed --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index f485763b2342..5d5e95590344 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -943,7 +943,7 @@ impl Option { // Transforming contained values ///////////////////////////////////////////////////////////////////////// - /// Maps an `Option` to `Option` by applying a function to a contained value (if `Some`) or return `None` (if `None`). + /// Maps an `Option` to `Option` by applying a function to a contained value (if `Some`) or returns `None` (if `None`). /// /// # Examples /// From 41883fd19a174b8c2d23494a24edd5b92b959fc6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 Feb 2023 02:29:52 +0000 Subject: [PATCH 085/137] intern external constraints --- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/traits/mod.rs | 1 + compiler/rustc_middle/src/traits/solve.rs | 55 +++++++++++++++++++ compiler/rustc_middle/src/ty/context.rs | 4 ++ .../rustc_trait_selection/src/solve/mod.rs | 35 ++++++------ .../src/solve/search_graph/cache.rs | 3 +- triagebot.toml | 3 +- 7 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 compiler/rustc_middle/src/traits/solve.rs diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 72f4f6e649bc..2ba7ec5b1519 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -112,6 +112,7 @@ macro_rules! arena_types { [decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, [] bit_set_u32: rustc_index::bit_set::BitSet, + [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, ]); ) } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index cf3dce480649..75525059e90d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -5,6 +5,7 @@ mod chalk; pub mod query; pub mod select; +pub mod solve; pub mod specialization_graph; mod structural_impls; pub mod util; diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs new file mode 100644 index 000000000000..63f9c32f0a74 --- /dev/null +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -0,0 +1,55 @@ +use std::ops::ControlFlow; + +use rustc_data_structures::intern::Interned; + +use crate::ty::{FallibleTypeFolder, Ty, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor}; + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); + +impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { + type Target = ExternalConstraintsData<'tcx>; + + fn deref(&self) -> &Self::Target { + &*self.0 + } +} + +/// Additional constraints returned on success. +#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)] +pub struct ExternalConstraintsData<'tcx> { + // FIXME: implement this. + pub regions: (), + pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, +} + +impl<'tcx> TypeFoldable<'tcx> for ExternalConstraints<'tcx> { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(FallibleTypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData { + regions: (), + opaque_types: self + .opaque_types + .iter() + .map(|opaque| opaque.try_fold_with(folder)) + .collect::>()?, + })) + } + + fn fold_with>(self, folder: &mut F) -> Self { + TypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData { + regions: (), + opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), + }) + } +} + +impl<'tcx> TypeVisitable<'tcx> for ExternalConstraints<'tcx> { + fn visit_with>( + &self, + visitor: &mut V, + ) -> std::ops::ControlFlow { + self.regions.visit_with(visitor)?; + self.opaque_types.visit_with(visitor)?; + ControlFlow::Continue(()) + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f98172e42016..9205a8a0ffed 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -17,6 +17,7 @@ use crate::mir::{ }; use crate::thir::Thir; use crate::traits; +use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData}; use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar, @@ -148,6 +149,7 @@ pub struct CtxtInterners<'tcx> { bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, adt_def: InternedSet<'tcx, AdtDefData>, + external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -169,6 +171,7 @@ impl<'tcx> CtxtInterners<'tcx> { bound_variable_kinds: Default::default(), layout: Default::default(), adt_def: Default::default(), + external_constraints: Default::default(), } } @@ -1449,6 +1452,7 @@ direct_interners! { const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, + external_constraints: intern_external_constraints(ExternalConstraintsData<'tcx>): ExternalConstraints -> ExternalConstraints<'tcx>, } macro_rules! slice_interners { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 36170b3788a7..e4725c0a1b73 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -24,7 +24,8 @@ use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; use rustc_middle::infer::canonical::Certainty as OldCertainty; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate, }; @@ -72,8 +73,7 @@ impl<'tcx, P> From> for Goal<'tcx, P> { Goal { param_env: obligation.param_env, predicate: obligation.predicate } } } - -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] pub struct Response<'tcx> { pub var_values: CanonicalVarValues<'tcx>, /// Additional constraints returned by this query. @@ -121,14 +121,6 @@ pub enum MaybeCause { Overflow, } -/// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)] -pub struct ExternalConstraints<'tcx> { - // FIXME: implement this. - regions: (), - opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, -} - type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>; type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>; /// The result of evaluating a canonical query. @@ -218,15 +210,14 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false }; let result = ecx.compute_goal(goal); - // FIXME: `Response` should be `Copy` - if search_graph.try_finalize_goal(tcx, canonical_goal, result.clone()) { + if search_graph.try_finalize_goal(tcx, canonical_goal, result) { return result; } } } fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> { - let external_constraints = take_external_constraints(self.infcx)?; + let external_constraints = compute_external_query_constraints(self.infcx)?; Ok(self.infcx.canonicalize_response(Response { var_values: self.var_values, @@ -461,18 +452,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } #[instrument(level = "debug", skip(infcx), ret)] -fn take_external_constraints<'tcx>( +fn compute_external_query_constraints<'tcx>( infcx: &InferCtxt<'tcx>, ) -> Result, NoSolution> { let region_obligations = infcx.take_registered_region_obligations(); let opaque_types = infcx.take_opaque_types_for_query_response(); - Ok(ExternalConstraints { + Ok(infcx.tcx.intern_external_constraints(ExternalConstraintsData { // FIXME: Now that's definitely wrong :) // // Should also do the leak check here I think regions: drop(region_obligations), opaque_types, - }) + })) } fn instantiate_canonical_query_response<'tcx>( @@ -492,7 +483,10 @@ fn instantiate_canonical_query_response<'tcx>( Certainty::Yes => OldCertainty::Proven, Certainty::Maybe(_) => OldCertainty::Ambiguous, }, - opaque_types: resp.external_constraints.opaque_types, + // FIXME: This to_owned makes me sad, but we should eventually impl + // `instantiate_query_response_and_region_obligations` separately + // instead of piggybacking off of the old implementation. + opaque_types: resp.external_constraints.opaque_types.to_owned(), value: resp.certainty, }), ) else { bug!(); }; @@ -510,7 +504,10 @@ pub(super) fn response_no_constraints<'tcx>( variables: goal.variables, value: Response { var_values: CanonicalVarValues::make_identity(tcx, goal.variables), - external_constraints: Default::default(), + // FIXME: maybe we should store the "no response" version in tcx, like + // we do for tcx.types and stuff. + external_constraints: tcx + .intern_external_constraints(ExternalConstraintsData::default()), certainty, }, }) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs index 80a388b8498b..86b13c05f76a 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs @@ -95,8 +95,7 @@ impl<'tcx> ProvisionalCache<'tcx> { } pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> { - // FIXME: Responses should probably be `Copy` as well - self.entries[entry_index].response.clone() + self.entries[entry_index].response } } diff --git a/triagebot.toml b/triagebot.toml index 79958729fc52..9e37eccb6d32 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -250,7 +250,8 @@ new_pr = true [autolabel."WG-trait-system-refactor"] trigger_files = [ - "compiler/rustc_trait_selection/src/solve" + "compiler/rustc_trait_selection/src/solve", + "compiler/rustc_middle/src/traits/solve.rs" ] [notify-zulip."I-prioritize"] From 0b5941aa1117b6054a6e991787e8075adf392b11 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 14 Jan 2023 22:55:27 +0000 Subject: [PATCH 086/137] Make const/fn return params more suggestable --- .../rustc_hir_analysis/src/astconv/mod.rs | 12 +-- compiler/rustc_hir_analysis/src/collect.rs | 32 +++---- .../rustc_hir_analysis/src/collect/type_of.rs | 47 +++------ .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_hir_typeck/src/op.rs | 4 +- compiler/rustc_middle/src/ty/diagnostics.rs | 95 ++++++++++++++++++- compiler/rustc_middle/src/ty/fold.rs | 2 +- ...suggest-fn-ptr-for-fn-item-in-fn-ret.fixed | 12 +++ .../suggest-fn-ptr-for-fn-item-in-fn-ret.rs | 12 +++ ...uggest-fn-ptr-for-fn-item-in-fn-ret.stderr | 12 +++ 10 files changed, 163 insertions(+), 67 deletions(-) create mode 100644 tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed create mode 100644 tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs create mode 100644 tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index bec9f0ff0772..3d5f189e233b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2945,12 +2945,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if r.is_erased() { tcx.lifetimes.re_static } else { r } }); let span = ast_ty.span; - tcx.sess.emit_err(TypeofReservedKeywordUsed { - span, - ty, - opt_sugg: Some((span, Applicability::MachineApplicable)) - .filter(|_| ty.is_suggestable(tcx, false)), - }); + let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { + (ty, Some((span, Applicability::MachineApplicable))) + } else { + (ty, None) + }; + tcx.sess.emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); ty } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index cc7235a61c0b..80426c239ac8 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1199,28 +1199,22 @@ fn infer_return_ty_for_fn_sig<'tcx>( visitor.visit_ty(ty); let mut diag = bad_placeholder(tcx, visitor.0, "return type"); let ret_ty = fn_sig.output(); - if ret_ty.is_suggestable(tcx, false) { + if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) { diag.span_suggestion( ty.span, "replace with the correct return type", ret_ty, Applicability::MachineApplicable, ); - } else if matches!(ret_ty.kind(), ty::FnDef(..)) { - let fn_sig = ret_ty.fn_sig(tcx); - if fn_sig - .skip_binder() - .inputs_and_output - .iter() - .all(|t| t.is_suggestable(tcx, false)) - { - diag.span_suggestion( - ty.span, - "replace with the correct return type", - fn_sig, - Applicability::MachineApplicable, - ); - } + } else if matches!(ret_ty.kind(), ty::FnDef(..)) + && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false) + { + diag.span_suggestion( + ty.span, + "replace with the correct return type", + fn_sig, + Applicability::MachineApplicable, + ); } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { diag.span_suggestion( ty.span, @@ -1280,9 +1274,7 @@ fn suggest_impl_trait<'tcx>( let trait_name = tcx.item_name(trait_def_id); let args_tuple = substs.type_at(1); let ty::Tuple(types) = *args_tuple.kind() else { return None; }; - if !types.is_suggestable(tcx, false) { - return None; - } + let types = types.make_suggestable(tcx, false)?; let maybe_ret = if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") }; Some(format!( @@ -1337,7 +1329,7 @@ fn suggest_impl_trait<'tcx>( // FIXME(compiler-errors): We may benefit from resolving regions here. if ocx.select_where_possible().is_empty() && let item_ty = infcx.resolve_vars_if_possible(item_ty) - && item_ty.is_suggestable(tcx, false) + && let Some(item_ty) = item_ty.make_suggestable(tcx, false) && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty) { return Some(sugg); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index e7b0846e1035..c5522c94874d 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -8,7 +8,9 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -845,37 +847,23 @@ fn infer_placeholder_type<'a>( ) -> Ty<'a> { // Attempts to make the type nameable by turning FnDefs into FnPtrs. struct MakeNameable<'tcx> { - success: bool, tcx: TyCtxt<'tcx>, } - impl<'tcx> MakeNameable<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Self { - MakeNameable { success: true, tcx } - } - } - impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !self.success { - return ty; - } - - match ty.kind() { + let ty = match *ty.kind() { ty::FnDef(def_id, substs) => { - self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id).subst(self.tcx, substs)) + self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) } - // FIXME: non-capturing closures should also suggest a function pointer - ty::Closure(..) | ty::Generator(..) => { - self.success = false; - ty - } - _ => ty.super_fold_with(self), - } + _ => ty, + }; + + ty.super_fold_with(self) } } @@ -898,15 +886,11 @@ fn infer_placeholder_type<'a>( suggestions.clear(); } - // Suggesting unnameable types won't help. - let mut mk_nameable = MakeNameable::new(tcx); - let ty = mk_nameable.fold_ty(ty); - let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; - if let Some(sugg_ty) = sugg_ty { + if let Some(ty) = ty.make_suggestable(tcx, false) { err.span_suggestion( span, &format!("provide a type for the {item}", item = kind), - format!("{colon} {sugg_ty}"), + format!("{colon} {ty}"), Applicability::MachineApplicable, ); } else { @@ -923,15 +907,12 @@ fn infer_placeholder_type<'a>( let mut diag = bad_placeholder(tcx, vec![span], kind); if !ty.references_error() { - let mut mk_nameable = MakeNameable::new(tcx); - let ty = mk_nameable.fold_ty(ty); - let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; - if let Some(sugg_ty) = sugg_ty { + if let Some(ty) = ty.make_suggestable(tcx, false) { diag.span_suggestion( span, "replace with the correct type", - sugg_ty, - Applicability::MaybeIncorrect, + ty, + Applicability::MachineApplicable, ); } else { with_forced_trimmed_paths!(diag.span_note( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3f433a0928c5..11d47053ade7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -687,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { - if found.is_suggestable(self.tcx, false) { + if let Some(found) = found.make_suggestable(self.tcx, false) { err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() }); return true; } else if let ty::Closure(_, substs) = found.kind() diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 67769fe4478a..ba72aefe39c1 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -490,9 +490,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(output_def_id) = output_def_id && let Some(trait_def_id) = trait_def_id && self.tcx.parent(output_def_id) == trait_def_id - && output_ty.is_suggestable(self.tcx, false) + && let Some(output_ty) = output_ty.make_suggestable(self.tcx, false) { - Some(("Output", *output_ty)) + Some(("Output", output_ty)) } else { None } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 4b4518f61e8d..cd9b92701407 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,8 +3,9 @@ use std::ops::ControlFlow; use crate::ty::{ - visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque, - PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, + visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, + InferTy, Opaque, PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitor, }; use rustc_data_structures::fx::FxHashMap; @@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> { } } -pub trait IsSuggestable<'tcx> { +pub trait IsSuggestable<'tcx>: Sized { /// Whether this makes sense to suggest in a diagnostic. /// /// We filter out certain types and constants since they don't provide @@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> { /// Only if `infer_suggestable` is true, we consider type and const /// inference variables to be suggestable. fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool; + + fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option; } impl<'tcx, T> IsSuggestable<'tcx> for T where - T: TypeVisitable<'tcx>, + T: TypeVisitable<'tcx> + TypeFoldable<'tcx>, { fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool { self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue() } + + fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option { + self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok() + } } pub fn suggest_arbitrary_trait_bound<'tcx>( @@ -509,3 +516,83 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { c.super_visit_with(self) } } + +pub struct MakeSuggestableFolder<'tcx> { + tcx: TyCtxt<'tcx>, + infer_suggestable: bool, +} + +impl<'tcx> FallibleTypeFolder<'tcx> for MakeSuggestableFolder<'tcx> { + type Error = (); + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + let t = match *t.kind() { + Infer(InferTy::TyVar(_)) if self.infer_suggestable => t, + + FnDef(def_id, substs) => { + self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs)) + } + + // FIXME(compiler-errors): We could replace these with infer, I guess. + Closure(..) + | Infer(..) + | Generator(..) + | GeneratorWitness(..) + | Bound(_, _) + | Placeholder(_) + | Error(_) => { + return Err(()); + } + + Alias(Opaque, AliasTy { def_id, .. }) => { + let parent = self.tcx.parent(def_id); + if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) + && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind() + && parent_opaque_def_id == def_id + { + t + } else { + return Err(()); + } + } + + Param(param) => { + // FIXME: It would be nice to make this not use string manipulation, + // but it's pretty hard to do this, since `ty::ParamTy` is missing + // sufficient info to determine if it is synthetic, and we don't + // always have a convenient way of getting `ty::Generics` at the call + // sites we invoke `IsSuggestable::is_suggestable`. + if param.name.as_str().starts_with("impl ") { + return Err(()); + } + + t + } + + _ => t, + }; + + t.try_super_fold_with(self) + } + + fn try_fold_const(&mut self, c: Const<'tcx>) -> Result, ()> { + let c = match c.kind() { + ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c, + + ConstKind::Infer(..) + | ConstKind::Bound(..) + | ConstKind::Placeholder(..) + | ConstKind::Error(..) => { + return Err(()); + } + + _ => c, + }; + + c.try_super_fold_with(self) + } +} diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 1445bc1ed32e..8a0019bc0127 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -105,7 +105,7 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { /// the infallible methods of this trait to ensure that the two APIs /// are coherent. pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; + fn tcx(&self) -> TyCtxt<'tcx>; fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed new file mode 100644 index 000000000000..abb9ef917743 --- /dev/null +++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +#![allow(unused)] + +struct Wrapper(T); + +fn bar() -> Wrapper { Wrapper(foo) } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + +fn foo() {} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs new file mode 100644 index 000000000000..d2a79c386941 --- /dev/null +++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs @@ -0,0 +1,12 @@ +// run-rustfix + +#![allow(unused)] + +struct Wrapper(T); + +fn bar() -> _ { Wrapper(foo) } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + +fn foo() {} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr new file mode 100644 index 000000000000..347a038525b6 --- /dev/null +++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-fn-ptr-for-fn-item-in-fn-ret.rs:7:13 + | +LL | fn bar() -> _ { Wrapper(foo) } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Wrapper` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. From e6c56cda09633c0388ef4c6c9e97d064db829cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 3 Feb 2023 23:41:39 +0000 Subject: [PATCH 087/137] review comments --- .../src/diagnostics/mutability_errors.rs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index cf3240226fb3..9f37b915b773 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -606,12 +606,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } Some((false, err_label_span, message)) => { - struct V { + struct BindingFinder { span: Span, hir_id: Option, } - impl<'tcx> Visitor<'tcx> for V { + impl<'tcx> Visitor<'tcx> for BindingFinder { fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { if let hir::StmtKind::Local(local) = s.kind { if local.pat.span == self.span { @@ -622,20 +622,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } let hir_map = self.infcx.tcx.hir(); - let pat = loop { - // Poor man's try block - let def_id = self.body.source.def_id(); - let hir_id = - hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap()); - let node = hir_map.find(hir_id); - let Some(hir::Node::Item(item)) = node else { break None; }; - let hir::ItemKind::Fn(.., body_id) = item.kind else { break None; }; - let body = self.infcx.tcx.hir().body(body_id); - let mut v = V { span: err_label_span, hir_id: None }; + let def_id = self.body.source.def_id(); + let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local()); + let node = hir_map.find(hir_id); + let hir_id = if let Some(hir::Node::Item(item)) = node + && let hir::ItemKind::Fn(.., body_id) = item.kind + { + let body = hir_map.body(body_id); + let mut v = BindingFinder { + span: err_label_span, + hir_id: None, + }; v.visit_body(body); - break v.hir_id; + v.hir_id + } else { + None }; - if let Some(hir_id) = pat + if let Some(hir_id) = hir_id && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) { let (changing, span, sugg) = match local.ty { From d78fb1a0157f64e937b2cd1d9a575488e1e36b94 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 4 Feb 2023 11:48:50 +0000 Subject: [PATCH 088/137] Remove Esteban from review queues for a while --- triagebot.toml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index d54d80c5adb5..62a99b704388 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -441,15 +441,15 @@ cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakar [mentions."compiler/rustc_error_messages"] message = "`rustc_error_messages` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_errors/src/translation.rs"] message = "`rustc_errors::translation` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_macros/src/diagnostics"] message = "`rustc_macros::diagnostics` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_target/src/spec"] message = """ @@ -475,7 +475,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" [assign.adhoc_groups] compiler-team = [ "@cjgillot", - "@estebank", "@petrochenkov", "@davidtwco", "@oli-obk", @@ -532,13 +531,11 @@ incremental = [ diagnostics = [ "@compiler-errors", "@davidtwco", - "@estebank", "@oli-obk", "@TaKO8Ki", ] parser = [ "@davidtwco", - "@estebank", "@nnethercote", "@petrochenkov", ] From ed58c01959bc69b42943292d7d5a8e86a821747e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 4 Feb 2023 13:27:53 +0100 Subject: [PATCH 089/137] don't point at nonexisting code beyond EOF when warning about unused delims Previously we would show this: ``` warning: unnecessary braces around block return value --> /tmp/bad.rs:1:8 | 1 | fn a(){{{ | ^ ^ | = note: `#[warn(unused_braces)]` on by default help: remove these braces | 1 - fn a(){{{ 1 + fn a(){{ | ``` which is now hidden in this case. We would create a span spanning between the pair of redundant {}s but there is only EOF instead of the `}` so we would previously point at nothing. This would cause the debug assertion ice to trigger. I would have loved to just only point at the second delim and say "you can remove that" but I'm not sure how to do that without refactoring the entire diagnostic which seems tricky. :( But given that this does not seem to regress any other tests we have, I think this edge-casey enough be acceptable. Fixes https://github.com/rust-lang/rust/issues/107423 r? @compiler-errors --- compiler/rustc_lint/src/unused.rs | 4 +++ ...ue-107423-unused-delim-only-one-no-pair.rs | 7 ++++ ...07423-unused-delim-only-one-no-pair.stderr | 32 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs create mode 100644 tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 4c9b3df2dbd3..2f54227c425b 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -661,6 +661,10 @@ trait UnusedDelimLint { keep_space: (bool, bool), ) { let primary_span = if let Some((lo, hi)) = spans { + if hi.is_empty() { + // do not point at delims that do not exist + return; + } MultiSpan::from(vec![lo, hi]) } else { MultiSpan::from(value_span) diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs new file mode 100644 index 000000000000..4003ee37ca1e --- /dev/null +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs @@ -0,0 +1,7 @@ +// check that we don't generate a span that points beyond EOF + +// error-pattern: unclosed delimiter +// error-pattern: unclosed delimiter +// error-pattern: unclosed delimiter + +fn a(){{{ diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr new file mode 100644 index 000000000000..0479035171e8 --- /dev/null +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 + | +LL | fn a(){{{ + | --- ^ + | ||| + | ||unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 + | +LL | fn a(){{{ + | --- ^ + | ||| + | ||unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 + | +LL | fn a(){{{ + | --- ^ + | ||| + | ||unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: aborting due to 3 previous errors + From 128f2224afa6bf135a674fc14e5c825f2c76c93f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 4 Feb 2023 15:16:59 +0000 Subject: [PATCH 090/137] Remove `OnHit` callback from query caches. This is not useful now that query results are `Copy`. --- compiler/rustc_middle/src/ty/query.rs | 62 ++++++---------- .../rustc_query_system/src/query/caches.rs | 73 +++++-------------- .../rustc_query_system/src/query/config.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 54 +++++++------- 4 files changed, 66 insertions(+), 125 deletions(-) diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 1be819ca610c..7151b79c5ab6 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -106,16 +106,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Helper for `TyCtxtEnsure` to avoid a closure. -#[inline(always)] -fn noop(_: &T) {} - -/// Helper to ensure that queries only return `Copy` types. -#[inline(always)] -fn copy(x: &T) -> T { - *x -} - macro_rules! query_helper_param_ty { (DefId) => { impl IntoQueryParam }; (LocalDefId) => { impl IntoQueryParam }; @@ -225,14 +215,10 @@ macro_rules! define_callbacks { let key = key.into_query_param(); opt_remap_env_constness!([$($modifiers)*][key]); - let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); - - match cached { - Ok(()) => return, - Err(()) => (), - } - - self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure); + match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) { + Some(_) => return, + None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure), + }; })* } @@ -254,14 +240,10 @@ macro_rules! define_callbacks { let key = key.into_query_param(); opt_remap_env_constness!([$($modifiers)*][key]); - let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy); - - match cached { - Ok(value) => return value, - Err(()) => (), + match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) { + Some(value) => value, + None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(), } - - self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap() })* } @@ -353,27 +335,25 @@ macro_rules! define_feedable { let tcx = self.tcx; let cache = &tcx.query_caches.$name; - let cached = try_get_cached(tcx, cache, &key, copy); - - match cached { - Ok(old) => { + match try_get_cached(tcx, cache, &key) { + Some(old) => { bug!( "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}", stringify!($name), - ); + ) + } + None => { + let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); + let dep_node_index = tcx.dep_graph.with_feed_task( + dep_node, + tcx, + key, + &value, + hash_result!([$($modifiers)*]), + ); + cache.complete(key, value, dep_node_index) } - Err(()) => (), } - - let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); - let dep_node_index = tcx.dep_graph.with_feed_task( - dep_node, - tcx, - key, - &value, - hash_result!([$($modifiers)*]), - ); - cache.complete(key, value, dep_node_index) } })* } diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 77d0d0314fc1..21c89cbc4f19 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -16,13 +16,13 @@ use std::marker::PhantomData; pub trait CacheSelector<'tcx, V> { type Cache where - V: Clone; + V: Copy; type ArenaCache; } pub trait QueryStorage { type Value: Debug; - type Stored: Clone; + type Stored: Copy; /// Store a value without putting it in the cache. /// This is meant to be used with cycle errors. @@ -36,14 +36,7 @@ pub trait QueryCache: QueryStorage + Sized { /// It returns the shard index and a lock guard to the shard, /// which will be used if the query is not in the cache and we need /// to compute it. - fn lookup( - &self, - key: &Self::Key, - // `on_hit` can be called while holding a lock to the query state shard. - on_hit: OnHit, - ) -> Result - where - OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R; + fn lookup(&self, key: &Self::Key) -> Option<(Self::Stored, DepNodeIndex)>; fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored; @@ -55,7 +48,7 @@ pub struct DefaultCacheSelector(PhantomData); impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector { type Cache = DefaultCache where - V: Clone; + V: Copy; type ArenaCache = ArenaCache<'tcx, K, V>; } @@ -72,7 +65,7 @@ impl Default for DefaultCache { } } -impl QueryStorage for DefaultCache { +impl QueryStorage for DefaultCache { type Value = V; type Stored = V; @@ -86,15 +79,12 @@ impl QueryStorage for DefaultCache { impl QueryCache for DefaultCache where K: Eq + Hash + Clone + Debug, - V: Clone + Debug, + V: Copy + Debug, { type Key = K; #[inline(always)] - fn lookup(&self, key: &K, on_hit: OnHit) -> Result - where - OnHit: FnOnce(&V, DepNodeIndex) -> R, - { + fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { let key_hash = sharded::make_hash(key); #[cfg(parallel_compiler)] let lock = self.cache.get_shard_by_hash(key_hash).lock(); @@ -102,12 +92,7 @@ where let lock = self.cache.lock(); let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key); - if let Some((_, value)) = result { - let hit_result = on_hit(&value.0, value.1); - Ok(hit_result) - } else { - Err(()) - } + if let Some((_, value)) = result { Some(*value) } else { None } } #[inline] @@ -176,10 +161,7 @@ where type Key = K; #[inline(always)] - fn lookup(&self, key: &K, on_hit: OnHit) -> Result - where - OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R, - { + fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> { let key_hash = sharded::make_hash(key); #[cfg(parallel_compiler)] let lock = self.cache.get_shard_by_hash(key_hash).lock(); @@ -187,12 +169,7 @@ where let lock = self.cache.lock(); let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key); - if let Some((_, value)) = result { - let hit_result = on_hit(&&value.0, value.1); - Ok(hit_result) - } else { - Err(()) - } + if let Some((_, value)) = result { Some((&value.0, value.1)) } else { None } } #[inline] @@ -234,7 +211,7 @@ pub struct VecCacheSelector(PhantomData); impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector { type Cache = VecCache where - V: Clone; + V: Copy; type ArenaCache = VecArenaCache<'tcx, K, V>; } @@ -251,7 +228,7 @@ impl Default for VecCache { } } -impl QueryStorage for VecCache { +impl QueryStorage for VecCache { type Value = V; type Stored = V; @@ -265,25 +242,17 @@ impl QueryStorage for VecCache { impl QueryCache for VecCache where K: Eq + Idx + Clone + Debug, - V: Clone + Debug, + V: Copy + Debug, { type Key = K; #[inline(always)] - fn lookup(&self, key: &K, on_hit: OnHit) -> Result - where - OnHit: FnOnce(&V, DepNodeIndex) -> R, - { + fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { #[cfg(parallel_compiler)] let lock = self.cache.get_shard_by_hash(key.index() as u64).lock(); #[cfg(not(parallel_compiler))] let lock = self.cache.lock(); - if let Some(Some(value)) = lock.get(*key) { - let hit_result = on_hit(&value.0, value.1); - Ok(hit_result) - } else { - Err(()) - } + if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None } } #[inline] @@ -357,20 +326,12 @@ where type Key = K; #[inline(always)] - fn lookup(&self, key: &K, on_hit: OnHit) -> Result - where - OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R, - { + fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> { #[cfg(parallel_compiler)] let lock = self.cache.get_shard_by_hash(key.index() as u64).lock(); #[cfg(not(parallel_compiler))] let lock = self.cache.lock(); - if let Some(Some(value)) = lock.get(*key) { - let hit_result = on_hit(&&value.0, value.1); - Ok(hit_result) - } else { - Err(()) - } + if let Some(Some(value)) = lock.get(*key) { Some((&value.0, value.1)) } else { None } } #[inline] diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 8c0330e438de..a28e45a5c086 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -21,7 +21,7 @@ pub trait QueryConfig { type Key: DepNodeParams + Eq + Hash + Clone + Debug; type Value: Debug; - type Stored: Debug + Clone + std::borrow::Borrow; + type Stored: Debug + Copy + std::borrow::Borrow; type Cache: QueryCache; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index b3b939eae88d..bf380f6e2d3b 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -130,7 +130,7 @@ fn mk_cycle( where Qcx: QueryContext + crate::query::HasDepContext, V: std::fmt::Debug + Value, - R: Clone, + R: Copy, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler); @@ -339,25 +339,21 @@ where /// which will be used if the query is not in the cache and we need /// to compute it. #[inline] -pub fn try_get_cached( - tcx: Tcx, - cache: &C, - key: &C::Key, - // `on_hit` can be called while holding a lock to the query cache - on_hit: OnHit, -) -> Result +pub fn try_get_cached(tcx: Tcx, cache: &C, key: &C::Key) -> Option where C: QueryCache, Tcx: DepContext, - OnHit: FnOnce(&C::Stored) -> R, { - cache.lookup(&key, |value, index| { - if std::intrinsics::unlikely(tcx.profiler().enabled()) { - tcx.profiler().query_cache_hit(index.into()); + match cache.lookup(&key) { + Some((value, index)) => { + if std::intrinsics::unlikely(tcx.profiler().enabled()) { + tcx.profiler().query_cache_hit(index.into()); + } + tcx.dep_graph().read_index(index); + Some(value) } - tcx.dep_graph().read_index(index); - on_hit(value) - }) + None => None, + } } fn try_execute_query( @@ -379,17 +375,25 @@ where if Q::FEEDABLE { // We may have put a value inside the cache from inside the execution. // Verify that it has the same hash as what we have now, to ensure consistency. - let _ = cache.lookup(&key, |cached_result, _| { + if let Some((cached_result, _)) = cache.lookup(&key) { let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash"); - let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow())); - let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); + let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| { + hasher(&mut hcx, cached_result.borrow()) + }); + let new_hash = qcx + .dep_context() + .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); debug_assert_eq!( - old_hash, new_hash, + old_hash, + new_hash, "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}", - Q::DEP_KIND, key, result, cached_result, + Q::DEP_KIND, + key, + result, + cached_result, ); - }); + } } let result = job.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) @@ -771,15 +775,11 @@ where // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. let cache = Q::query_cache(qcx); - let cached = cache.lookup(&key, |_, index| { + if let Some((_, index)) = cache.lookup(&key) { if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { qcx.dep_context().profiler().query_cache_hit(index.into()); } - }); - - match cached { - Ok(()) => return, - Err(()) => {} + return; } let state = Q::query_state(qcx); From 635ff8e2a8ee1acc3bc5144606d9d12f9ac62d98 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 4 Feb 2023 15:56:21 +0000 Subject: [PATCH 091/137] Support parallel compiler. --- compiler/rustc_query_system/src/query/plumbing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index bf380f6e2d3b..ffc413d15f52 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -404,9 +404,9 @@ where } #[cfg(parallel_compiler)] TryGetJob::JobCompleted(query_blocked_prof_timer) => { - let (v, index) = cache - .lookup(&key, |value, index| (value.clone(), index)) - .unwrap_or_else(|_| panic!("value must be in cache after waiting")); + let Some((v, index)) = cache.lookup(&key) else { + panic!("value must be in cache after waiting") + }; if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) { qcx.dep_context().profiler().query_cache_hit(index.into()); From b1c4911b2a2e936827996345bbdc65a9bfa650f2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 4 Feb 2023 10:14:08 -0700 Subject: [PATCH 092/137] rustdoc: combine duplicate rules in ayu CSS --- src/librustdoc/html/static/css/themes/ayu.css | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index d20d13ab36d2..b5a2cf7f28bf 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -105,10 +105,9 @@ Original by Dempfi (https://github.com/dempfi/ayu) --scrape-example-code-wrapper-background-end: rgba(15, 20, 25, 0); } -h1, h2, h3, h4 { - color: white; -} -h1 a { +h1, h2, h3, h4, +h1 a, .sidebar h2 a, .sidebar h3 a, +#source-sidebar > .title { color: #fff; } h4 { @@ -118,24 +117,22 @@ h4 { .docblock code { color: #ffb454; } -.code-header { - color: #e6e1cf; -} -.docblock pre > code, pre > code { - color: #e6e1cf; -} -.item-info code { - color: #e6e1cf; -} .docblock a > code { color: #39AFD7 !important; } -pre, .rustdoc.source .example-wrap { +.code-header, +.docblock pre > code, +pre, pre > code, +.item-info code, +.rustdoc.source .example-wrap { color: #e6e1cf; } .sidebar .current, -.sidebar a:hover { +.sidebar a:hover, +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus, +#source-sidebar div.files > a.selected { color: #ffb44c; } @@ -149,15 +146,12 @@ pre, .rustdoc.source .example-wrap { border-right: 1px solid #ffb44c; } -.search-results a:hover { - color: #fff !important; - background-color: #3c3c3c; -} - +.search-results a:hover, .search-results a:focus { color: #fff !important; background-color: #3c3c3c; } + .search-results a { color: #0096cf; } @@ -165,11 +159,6 @@ pre, .rustdoc.source .example-wrap { color: #c5c5c5; } -.sidebar h2 a, -.sidebar h3 a { - color: white; -} - .result-name .primitive > i, .result-name .keyword > i { color: #788797; } @@ -189,12 +178,3 @@ pre, .rustdoc.source .example-wrap { #settings-menu > a img { filter: invert(100); } - -#source-sidebar > .title { - color: #fff; -} -#source-sidebar div.files > a:hover, details.dir-entry summary:hover, -#source-sidebar div.files > a:focus, details.dir-entry summary:focus, -#source-sidebar div.files > a.selected { - color: #ffb44c; -} From 6558326e7b5f8f5591b0a1289bc48099ae473a01 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Fri, 20 Jan 2023 11:04:44 +0300 Subject: [PATCH 093/137] consolidate bootstrap docs Signed-off-by: ozkanonur --- src/bootstrap/README.md | 199 ++++++++-------------------------------- src/bootstrap/lib.rs | 87 ------------------ 2 files changed, 38 insertions(+), 248 deletions(-) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 8dce9e79e16b..71eee8968e27 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -4,105 +4,31 @@ This is an in-progress README which is targeted at helping to explain how Rust is bootstrapped and in general, some of the technical details of the build system. -## Using rustbuild +Note that this README only covers internal information, not how to use the tool. +Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information. -The rustbuild build system has a primary entry point, a top level `x.py` script: +[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html -```sh -$ python ./x.py build -``` +## Introduction -Note that if you're on Unix, you should be able to execute the script directly: +The build system defers most of the complicated logic managing invocations +of rustc and rustdoc to Cargo itself. However, moving through various stages +and copying artifacts is still necessary for it to do. Each time rustbuild +is invoked, it will iterate through the list of predefined steps and execute +each serially in turn if it matches the paths passed or is a default rule. +For each step rustbuild relies on the step internally being incremental and +parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded +to appropriate test harnesses and such. -```sh -$ ./x.py build -``` - -The script accepts commands, flags, and arguments to determine what to do: - -* `build` - a general purpose command for compiling code. Alone, `build` will - bootstrap the entire compiler, and otherwise, arguments passed indicate what to - build. For example: - - ``` - # build the whole compiler - ./x.py build --stage 2 - - # build the stage1 compiler - ./x.py build - - # build stage0 libstd - ./x.py build --stage 0 library/std - - # build a particular crate in stage0 - ./x.py build --stage 0 library/test - ``` - - If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be - overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps - that belong to stage n or earlier: - - ``` - # build stage 1, keeping old build products for stage 0 - ./x.py build --keep-stage 0 - ``` - -* `test` - a command for executing unit tests. Like the `build` command, this - will execute the entire test suite by default, and otherwise, it can be used to - select which test suite is run: - - ``` - # run all unit tests - ./x.py test - - # execute tool tests - ./x.py test tidy - - # execute the UI test suite - ./x.py test tests/ui - - # execute only some tests in the UI test suite - ./x.py test tests/ui --test-args substring-of-test-name - - # execute tests in the standard library in stage0 - ./x.py test --stage 0 library/std - - # execute tests in the core and standard library in stage0, - # without running doc tests (thus avoid depending on building the compiler) - ./x.py test --stage 0 --no-doc library/core library/std - - # execute all doc tests - ./x.py test src/doc - ``` - -* `doc` - a command for building documentation. Like above, can take arguments - for what to document. - -## Configuring rustbuild - -rustbuild offers a TOML-based configuration system with a `config.toml` -file. An example of this configuration can be found at `config.toml.example`, -and the configuration file can also be passed as `--config path/to/config.toml` -if the build system is being invoked manually (via the python script). - -You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it. - -Finally, rustbuild makes use of the [cc-rs crate] which has [its own -method][env-vars] of configuring C compilers and C flags via environment -variables. - -[cc-rs crate]: https://github.com/alexcrichton/cc-rs -[env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables - -## Build stages +## Build phases The rustbuild build system goes through a few phases to actually build the compiler. What actually happens when you invoke rustbuild is: -1. The entry point script, `x.py` is run. This script is - responsible for downloading the stage0 compiler/Cargo binaries, and it then - compiles the build system itself (this folder). Finally, it then invokes the - actual `bootstrap` binary build system. +1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems, + `x.py` cross-platform) is run. This script is responsible for downloading the stage0 + compiler/Cargo binaries, and it then compiles the build system itself (this folder). + Finally, it then invokes the actual `bootstrap` binary build system. 2. In Rust, `bootstrap` will slurp up all configuration, perform a number of sanity checks (whether compilers exist, for example), and then start building the stage0 artifacts. @@ -115,24 +41,6 @@ compiler. What actually happens when you invoke rustbuild is: The goal of each stage is to (a) leverage Cargo as much as possible and failing that (b) leverage Rust as much as possible! -## Incremental builds - -You can configure rustbuild to use incremental compilation with the -`--incremental` flag: - -```sh -$ ./x.py build --incremental -``` - -The `--incremental` flag will store incremental compilation artifacts -in `build//stage0-incremental`. Note that we only use incremental -compilation for the stage0 -> stage1 compilation -- this is because -the stage1 compiler is changing, and we don't try to cache and reuse -incremental artifacts across different versions of the compiler. - -You can always drop the `--incremental` to build as normal (but you -will still be using the local nightly as your bootstrap). - ## Directory Layout This build system houses all output under the `build` directory, which looks @@ -236,63 +144,31 @@ build/ # system will link (using hard links) output from stageN-{std,rustc} into # each of these directories. # - # In theory, there is no extra build output in these directories. + # In theory these are working rustc sysroot directories, meaning there is + # no extra build output in these directories. stage1/ stage2/ stage3/ ``` -## Cargo projects - -The current build is unfortunately not quite as simple as `cargo build` in a -directory, but rather the compiler is split into three different Cargo projects: - -* `library/std` - the standard library -* `library/test` - testing support, depends on libstd -* `compiler/rustc` - the actual compiler itself - -Each "project" has a corresponding Cargo.lock file with all dependencies, and -this means that building the compiler involves running Cargo three times. The -structure here serves two goals: - -1. Facilitating dependencies coming from crates.io. These dependencies don't - depend on `std`, so libstd is a separate project compiled ahead of time - before the actual compiler builds. -2. Splitting "host artifacts" from "target artifacts". That is, when building - code for an arbitrary target, you don't need the entire compiler, but you'll - end up needing libraries like libtest that depend on std but also want to use - crates.io dependencies. Hence, libtest is split out as its own project that - is sequenced after `std` but before `rustc`. This project is built for all - targets. - -There is some loss in build parallelism here because libtest can be compiled in -parallel with a number of rustc artifacts, but in theory, the loss isn't too bad! - -## Build tools - -We've actually got quite a few tools that we use in the compiler's build system -and for testing. To organize these, each tool is a project in `src/tools` with a -corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having -independent `Cargo.lock` files) and do not currently explicitly depend on the -compiler or standard library. Compiling each tool is sequenced after the -appropriate libstd/libtest/librustc compile above. - ## Extending rustbuild -So, you'd like to add a feature to the rustbuild build system or just fix a bug. -Great! One of the major motivational factors for moving away from `make` is that -Rust is in theory much easier to read, modify, and write. If you find anything -excessively confusing, please open an issue on this, and we'll try to get it -documented or simplified, pronto. +When you use the bootstrap system, you'll call it through the entry point script +(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. +`bootstrap` has a difficult problem: it is written in Rust, but yet it is run +before the Rust compiler is built! To work around this, there are two components +of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py` +is what gets run by entry point script. It takes care of downloading the `stage0` +compiler, which will then build the bootstrap binary written in Rust. -First up, you'll probably want to read over the documentation above, as that'll -give you a high level overview of what rustbuild is doing. You also probably -want to play around a bit yourself by just getting it up and running before you -dive too much into the actual build system itself. +Because there are two separate codebases behind `x.py`, they need to +be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary +parse `config.toml` and read the same command line arguments. `bootstrap.py` +keeps these in sync by setting various environment variables, and the +programs sometimes have to add arguments that are explicitly ignored, to be +read by the other. -After that, each module in rustbuild should have enough documentation to keep -you up and running. Some general areas that you may be interested in modifying -are: +Some general areas that you may be interested in modifying are: * Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of other tools. @@ -320,8 +196,9 @@ A 'major change' includes Changes that do not affect contributors to the compiler or users building rustc from source don't need an update to `VERSION`. -If you have any questions, feel free to reach out on the `#t-infra` channel in -the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When -you encounter bugs, please file issues on the rust-lang/rust issue tracker. +If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel +at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs, +please file issues on the [Rust issue tracker][rust-issue-tracker]. -[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra +[rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap +[rust-issue-tracker]: https://github.com/rust-lang/rust/issues diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d44b96cfb991..698edb52d8f0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -11,93 +11,6 @@ //! crates.io and Cargo. //! * A standard interface to build across all platforms, including MSVC //! -//! ## Architecture -//! -//! The build system defers most of the complicated logic managing invocations -//! of rustc and rustdoc to Cargo itself. However, moving through various stages -//! and copying artifacts is still necessary for it to do. Each time rustbuild -//! is invoked, it will iterate through the list of predefined steps and execute -//! each serially in turn if it matches the paths passed or is a default rule. -//! For each step rustbuild relies on the step internally being incremental and -//! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded -//! to appropriate test harnesses and such. -//! -//! Most of the "meaty" steps that matter are backed by Cargo, which does indeed -//! have its own parallelism and incremental management. Later steps, like -//! tests, aren't incremental and simply run the entire suite currently. -//! However, compiletest itself tries to avoid running tests when the artifacts -//! that are involved (mainly the compiler) haven't changed. -//! -//! When you execute `x.py build`, the steps executed are: -//! -//! * First, the python script is run. This will automatically download the -//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached -//! versions if they're available. These are then used to compile rustbuild -//! itself (using Cargo). Finally, control is then transferred to rustbuild. -//! -//! * Rustbuild takes over, performs sanity checks, probes the environment, -//! reads configuration, and starts executing steps as it reads the command -//! line arguments (paths) or going through the default rules. -//! -//! The build output will be something like the following: -//! -//! Building stage0 std artifacts -//! Copying stage0 std -//! Building stage0 test artifacts -//! Copying stage0 test -//! Building stage0 compiler artifacts -//! Copying stage0 rustc -//! Assembling stage1 compiler -//! Building stage1 std artifacts -//! Copying stage1 std -//! Building stage1 test artifacts -//! Copying stage1 test -//! Building stage1 compiler artifacts -//! Copying stage1 rustc -//! Assembling stage2 compiler -//! Uplifting stage1 std -//! Uplifting stage1 test -//! Uplifting stage1 rustc -//! -//! Let's disect that a little: -//! -//! ## Building stage0 {std,test,compiler} artifacts -//! -//! These steps use the provided (downloaded, usually) compiler to compile the -//! local Rust source into libraries we can use. -//! -//! ## Copying stage0 {std,test,rustc} -//! -//! This copies the build output from Cargo into -//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's -//! documentation should be expanded -- the information already here may be -//! incorrect. -//! -//! ## Assembling stage1 compiler -//! -//! This copies the libraries we built in "building stage0 ... artifacts" into -//! the stage1 compiler's lib directory. These are the host libraries that the -//! compiler itself uses to run. These aren't actually used by artifacts the new -//! compiler generates. This step also copies the rustc and rustdoc binaries we -//! generated into build/$HOST/stage/bin. -//! -//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have -//! any libraries to link built binaries or libraries to. The next 3 steps will -//! provide those libraries for it; they are mostly equivalent to constructing -//! the stage1/bin compiler so we don't go through them individually. -//! -//! ## Uplifting stage1 {std,test,rustc} -//! -//! This step copies the libraries from the stage1 compiler sysroot into the -//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries -//! we'd build in this step should be identical (in function, if not necessarily -//! identical on disk) so there's no need to recompile the compiler again. Note -//! that if you want to, you can enable the full-bootstrap option to change this -//! behavior. -//! -//! Each step is driven by a separate Cargo project and rustbuild orchestrates -//! copying files between steps and otherwise preparing for Cargo to run. -//! //! ## Further information //! //! More documentation can be found in each respective module below, and you can From 71a147df1f6fea8f023c5054e0e7591dfb2aa5ae Mon Sep 17 00:00:00 2001 From: Roland Strasser Date: Sat, 26 Nov 2022 01:51:50 +0100 Subject: [PATCH 094/137] rustdoc: trait bound formatting rustdoc: fix item-spacer rustdoc: use proper comment style rustdoc: change formatting where clauses for traits rustdoc: remove semicolon from provided methods update provided methods formatting --- src/librustdoc/html/format.rs | 12 +++++++++-- src/librustdoc/html/render/print_item.rs | 20 +++++++++---------- src/librustdoc/html/static/css/rustdoc.css | 1 + .../auxiliary/inline-default-methods.rs | 12 +++++++++++ .../decl-trailing-whitespace.declaration.html | 4 +++- tests/rustdoc/inline-default-methods.rs | 16 +++++++++++++-- tests/rustdoc/issue-85454.rs | 4 ++-- .../where.SWhere_TraitWhere_item-decl.html | 10 +++++----- tests/rustdoc/where.rs | 6 ++++++ .../whitespace-after-where-clause.trait.html | 1 + .../whitespace-after-where-clause.trait2.html | 1 + 11 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 74cdf9b9b798..a59cfbea8853 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -353,7 +353,11 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( } else { let mut br_with_padding = String::with_capacity(6 * indent + 28); br_with_padding.push_str("
"); - for _ in 0..indent + 4 { + + let padding_amout = + if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() }; + + for _ in 0..padding_amout { br_with_padding.push_str(" "); } let where_preds = where_preds.to_string().replace("
", &br_with_padding); @@ -367,8 +371,12 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( if indent == 0 { format!("
where{where_preds}") } else { + // put the first one on the same line as the 'where' keyword + let where_preds = where_preds.replacen(&br_with_padding, " ", 1); + let mut clause = br_with_padding; - clause.truncate(clause.len() - 4); + clause.truncate(clause.len() - "where ".len()); + write!(clause, "where{where_preds}")?; clause } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 9a7a08ab8068..c2d24e514845 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -645,6 +645,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if count_consts != 0 && count_methods != 0 { w.write_str("\n"); } + + if !required_methods.is_empty() { + write!(w, " // Required method{}\n", pluralize(required_methods.len())); + } for (pos, m) in required_methods.iter().enumerate() { render_assoc_item( w, @@ -663,6 +667,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if !required_methods.is_empty() && !provided_methods.is_empty() { w.write_str("\n"); } + + if !provided_methods.is_empty() { + write!(w, " // Provided method{}\n", pluralize(provided_methods.len())); + } for (pos, m) in provided_methods.iter().enumerate() { render_assoc_item( w, @@ -672,16 +680,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: cx, RenderMode::Normal, ); - match *m.kind { - clean::MethodItem(ref inner, _) - if !inner.generics.where_predicates.is_empty() => - { - w.write_str(",\n { ... }\n"); - } - _ => { - w.write_str(" { ... }\n"); - } - } + + w.write_str(" { ... }\n"); if pos < provided_methods.len() - 1 { w.write_str(""); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a1e91118303c..2a9548712f08 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1176,6 +1176,7 @@ a.test-arrow:hover { .item-spacer { width: 100%; height: 12px; + display: block; } .out-of-band > span.since { diff --git a/tests/rustdoc/auxiliary/inline-default-methods.rs b/tests/rustdoc/auxiliary/inline-default-methods.rs index 8a636f449210..f06a20b27dce 100644 --- a/tests/rustdoc/auxiliary/inline-default-methods.rs +++ b/tests/rustdoc/auxiliary/inline-default-methods.rs @@ -4,3 +4,15 @@ pub trait Foo { fn bar(&self); fn foo(&mut self) {} } + +pub trait Bar { + fn bar(&self); + fn foo1(&mut self) {} + fn foo2(&mut self) {} +} + +pub trait Baz { + fn bar1(&self); + fn bar2(&self); + fn foo(&mut self) {} +} diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html index 02b51b344619..a2500de79a09 100644 --- a/tests/rustdoc/decl-trailing-whitespace.declaration.html +++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html @@ -1,7 +1,9 @@ pub trait Write { + // Required methods fn poll_write(
        self: Option<String>,
        cx: &mut Option<String>,
        buf: &mut [usize]
    ) -> Option<Result<usize, Error>>; fn poll_flush(
        self: Option<String>,
        cx: &mut Option<String>
    ) -> Option<Result<(), Error>>; fn poll_close(
        self: Option<String>,
        cx: &mut Option<String>
    ) -> Option<Result<(), Error>>; + // Provided method fn poll_write_vectored(
        self: Option<String>,
        cx: &mut Option<String>,
        bufs: &[usize]
    ) -> Option<Result<usize, Error>> { ... } -}
\ No newline at end of file +}
diff --git a/tests/rustdoc/inline-default-methods.rs b/tests/rustdoc/inline-default-methods.rs index e6468316f583..7706cb139ac9 100644 --- a/tests/rustdoc/inline-default-methods.rs +++ b/tests/rustdoc/inline-default-methods.rs @@ -4,6 +4,18 @@ extern crate inline_default_methods; // @has inline_default_methods/trait.Foo.html -// @has - '//pre[@class="rust item-decl"]' 'fn bar(&self);' -// @has - '//pre[@class="rust item-decl"]' 'fn foo(&mut self) { ... }' +// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);' +// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)' pub use inline_default_methods::Foo; + +// @has inline_default_methods/trait.Bar.html +// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);' +// @has - '//pre[@class="rust item-decl"]' '// Provided methods fn foo1(&mut self)' +// @has - '//pre[@class="rust item-decl"]' 'fn foo2(&mut self)' +pub use inline_default_methods::Bar; + +// @has inline_default_methods/trait.Baz.html +// @has - '//pre[@class="rust item-decl"]' '// Required methods fn bar1(&self);' +// @has - '//pre[@class="rust item-decl"]' 'fn bar2(&self);' +// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)' +pub use inline_default_methods::Baz; diff --git a/tests/rustdoc/issue-85454.rs b/tests/rustdoc/issue-85454.rs index 2d410a5974af..5a49a9d06519 100644 --- a/tests/rustdoc/issue-85454.rs +++ b/tests/rustdoc/issue-85454.rs @@ -5,7 +5,7 @@ extern crate issue_85454; // @has foo/trait.FromResidual.html -// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }' +// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { // Required method fn from_residual(residual: R) -> Self; }' pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; } @@ -24,6 +24,6 @@ pub enum ControlFlow { pub mod reexport { // @has foo/reexport/trait.FromResidual.html - // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }' + // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { // Required method fn from_residual(residual: R) -> Self; }' pub use issue_85454::*; } diff --git a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html index 11df902f3720..858bc142f66e 100644 --- a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html +++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html @@ -1,8 +1,8 @@
pub trait TraitWhere {
-    type Item<'a>
    where
        Self: 'a
; + type Item<'a>
       where Self: 'a; - fn func(self)
    where
        Self: Sized
, - { ... } - fn lines(self) -> Lines<Self>
    where
        Self: Sized
, - { ... } + // Provided methods + fn func(self)
       where Self: Sized { ... } + fn lines(self) -> Lines<Self>
       where Self: Sized { ... } + fn merge<T>(self, a: T)
       where Self: Sized,
             T: Sized
{ ... } }
\ No newline at end of file diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs index 4c34c7e51d93..af3239b69470 100644 --- a/tests/rustdoc/where.rs +++ b/tests/rustdoc/where.rs @@ -41,6 +41,12 @@ pub trait TraitWhere { where Self: Sized, { todo!() } + + fn merge(self, a: T) + where + Self: Sized, + T: Sized, + { todo!() } } // @has foo/struct.Echo.html '//*[@class="impl"]//h3[@class="code-header"]' \ diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html index bc3653de52d1..8a78e82dc71d 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait.html @@ -1,6 +1,7 @@
pub trait ToOwned<T>where
    T: Clone,
{ type Owned; + // Required methods fn to_owned(&self) -> Self::Owned; fn whatever(&self) -> T; }
\ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.trait2.html b/tests/rustdoc/whitespace-after-where-clause.trait2.html index eda4ca72acc1..e6fafde1effe 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait2.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait2.html @@ -1,6 +1,7 @@
pub trait ToOwned2<T: Clone> {
     type Owned;
 
+    // Required methods
     fn to_owned(&self) -> Self::Owned;
     fn whatever(&self) -> T;
 }
\ No newline at end of file From d9f60052d2471b15417153d3daca8d83d1c44fd4 Mon Sep 17 00:00:00 2001 From: Lenko Donchev Date: Wed, 1 Feb 2023 20:50:41 -0600 Subject: [PATCH 095/137] Recover from default value for a lifetime in generic parameters. --- .../locales/en-US/parse.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 8 ++++++++ compiler/rustc_parse/src/parser/generics.rs | 17 ++++++++++++++++- .../issue-107492-default-value-for-lifetime.rs | 6 ++++++ ...sue-107492-default-value-for-lifetime.stderr | 8 ++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs create mode 100644 tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 244eb41eb39e..827f96b6ac31 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -472,6 +472,9 @@ parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}` parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items +parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter + .label = lifetime parameters cannot have default values + parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item .label = previous `where` clause starts here .suggestion = consider joining the two `where` clauses into one diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fd4333dbbecc..0d09fb6a7c28 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1589,6 +1589,14 @@ pub(crate) struct UnexpectedSelfInGenericParameters { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)] +pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters { + #[primary_span] + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_multiple_where_clauses)] pub(crate) struct MultipleWhereClauses { diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 585dfc518b32..23f49ec55a18 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,5 +1,6 @@ use crate::errors::{ - MultipleWhereClauses, UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, + MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, + UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, WhereClauseBeforeTupleStructBodySugg, }; @@ -145,6 +146,20 @@ impl<'a> Parser<'a> { } else { (None, Vec::new()) }; + + if this.check_noexpect(&token::Eq) + && this.look_ahead(1, |t| t.is_lifetime()) + { + let lo = this.token.span; + // Parse `= 'lifetime`. + this.bump(); // `=` + this.bump(); // `'lifetime` + let span = lo.to(this.prev_token.span); + this.sess.emit_err( + UnexpectedDefaultValueForLifetimeInGenericParameters { span }, + ); + } + Some(ast::GenericParam { ident: lifetime.ident, id: lifetime.id, diff --git a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs new file mode 100644 index 000000000000..f129035d040f --- /dev/null +++ b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs @@ -0,0 +1,6 @@ +pub struct DefaultLifetime<'a, 'b = 'static> { + //~^ ERROR unexpected default lifetime parameter + _marker: std::marker::PhantomData<&'a &'b ()>, +} + +fn main(){} diff --git a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr new file mode 100644 index 000000000000..c235c31809fb --- /dev/null +++ b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr @@ -0,0 +1,8 @@ +error: unexpected default lifetime parameter + --> $DIR/issue-107492-default-value-for-lifetime.rs:1:35 + | +LL | pub struct DefaultLifetime<'a, 'b = 'static> { + | ^^^^^^^^^ lifetime parameters cannot have default values + +error: aborting due to previous error + From 60e82aef64ed62a40ec06357a9946196909ce953 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 01:07:25 +0100 Subject: [PATCH 096/137] rustc_expand: remove huge error imports --- compiler/rustc_expand/src/base.rs | 48 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 5a48473d5b07..cf7cff739b34 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,11 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] -use crate::errors::{ - ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord, - AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid, - MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord, - ResolveRelativePath, TakesNoArguments, TraceMacro, -}; +use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -796,13 +791,13 @@ impl SyntaxExtension { .unwrap_or_else(|| (None, helper_attrs)); let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span); if let Some((_, sp)) = const_stability { - sess.emit_err(MacroConstStability { + sess.emit_err(errors::MacroConstStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); } if let Some((_, sp)) = body_stability { - sess.emit_err(MacroBodyStability { + sess.emit_err(errors::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); @@ -1143,7 +1138,7 @@ impl<'a> ExtCtxt<'a> { } pub fn trace_macros_diag(&mut self) { for (span, notes) in self.expansions.iter() { - let mut db = self.sess.parse_sess.create_note(TraceMacro { span: *span }); + let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span }); for note in notes { db.note(note); } @@ -1197,7 +1192,7 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(ResolveRelativePath { + return Err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), } @@ -1279,7 +1274,7 @@ pub fn expr_to_string( /// done as rarely as possible). pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) { if !tts.is_empty() { - cx.emit_err(TakesNoArguments { span, name }); + cx.emit_err(errors::TakesNoArguments { span, name }); } } @@ -1307,14 +1302,14 @@ pub fn get_single_str_from_tts( ) -> Option { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - cx.emit_err(OnlyOneArgument { span, name }); + cx.emit_err(errors::OnlyOneArgument { span, name }); return None; } let ret = parse_expr(&mut p)?; let _ = p.eat(&token::Comma); if p.token != token::Eof { - cx.emit_err(OnlyOneArgument { span, name }); + cx.emit_err(errors::OnlyOneArgument { span, name }); } expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) } @@ -1336,7 +1331,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option trait_ident, _ => { - diag.emit_err(OnlyOneWord { span: trait_attr.span }); + diag.emit_err(errors::OnlyOneWord { span: trait_attr.span }); return None; } }; if !trait_ident.name.can_be_raw() { - diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type }); + diag.emit_err(errors::CannotBeNameOfMacro { + span: trait_attr.span, + trait_ident, + macro_type, + }); } let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { if !attr.has_name(sym::attributes) { - diag.emit_err(ArgumentNotAttributes { span: attr.span() }); + diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() }); } attr.meta_item_list() .unwrap_or_else(|| { - diag.emit_err(AttributesWrongForm { span: attr.span() }); + diag.emit_err(errors::AttributesWrongForm { span: attr.span() }); &[] }) .iter() .filter_map(|attr| { let Some(attr) = attr.meta_item() else { - diag.emit_err(AttributeMetaItem { span: attr.span() }); + diag.emit_err(errors::AttributeMetaItem { span: attr.span() }); return None; }; let ident = match attr.ident() { Some(ident) if attr.is_word() => ident, _ => { - diag.emit_err(AttributeSingleWord { span: attr.span }); + diag.emit_err(errors::AttributeSingleWord { span: attr.span }); return None; } }; if !ident.name.can_be_raw() { - diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident }); + diag.emit_err(errors::HelperAttributeNameInvalid { + span: attr.span, + name: ident, + }); } Some(ident.name) From 4442f13b030162319cfe53335d4abc369f75214b Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 01:58:22 +0100 Subject: [PATCH 097/137] rustc_metadata: remove huge error imports --- compiler/rustc_metadata/src/creader.rs | 28 +++--- compiler/rustc_metadata/src/locator.rs | 50 +++++----- compiler/rustc_metadata/src/native_libs.rs | 103 ++++++++++----------- 3 files changed, 89 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 44d6c587da3d..21652063b471 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,10 +1,6 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::errors::{ - ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime, - GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy, - NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore, -}; +use crate::errors; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -768,10 +764,11 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.emit_err(CrateNotPanicRuntime { crate_name: name }); + self.sess.emit_err(errors::CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy }); + self.sess + .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -791,7 +788,7 @@ impl<'a> CrateLoader<'a> { let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) { - self.sess.emit_err(ProfilerBuiltinsNeedsCore); + self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore); } let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; @@ -799,21 +796,22 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.emit_err(NotProfilerRuntime { crate_name: name }); + self.sess.emit_err(errors::NotProfilerRuntime { crate_name: name }); } } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { [span1, span2, ..] => { - self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); + self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), }; self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) { [span1, span2, ..] => { - self.sess.emit_err(NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); + self.sess + .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), @@ -849,7 +847,7 @@ impl<'a> CrateLoader<'a> { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.sess.emit_err(ConflictingGlobalAlloc { + self.sess.emit_err(errors::ConflictingGlobalAlloc { crate_name: data.name(), other_crate_name: other_crate, }); @@ -864,7 +862,7 @@ impl<'a> CrateLoader<'a> { if data.has_alloc_error_handler() { match alloc_error_handler { Some(other_crate) => { - self.sess.emit_err(ConflictingAllocErrorHandler { + self.sess.emit_err(errors::ConflictingAllocErrorHandler { crate_name: data.name(), other_crate_name: other_crate, }); @@ -884,7 +882,7 @@ impl<'a> CrateLoader<'a> { if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.sess.emit_err(GlobalAllocRequired); + self.sess.emit_err(errors::GlobalAllocRequired); } self.cstore.allocator_kind = Some(AllocatorKind::Default); } @@ -917,7 +915,7 @@ impl<'a> CrateLoader<'a> { for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { - self.sess.emit_err(NoTransitiveNeedsDep { + self.sess.emit_err(errors::NoTransitiveNeedsDep { crate_name: self.cstore.get_crate_data(krate).name(), needs_crate_name: what, deps_crate_name: data.name(), diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 0f5f74007c10..74f91a14ea9a 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,12 +213,7 @@ //! metadata::locator or metadata::creader for all the juicy details! use crate::creader::Library; -use crate::errors::{ - CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, - ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, - LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, - NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers, -}; +use crate::errors; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -980,28 +975,28 @@ impl CrateError { pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) { match self { CrateError::NonAsciiName(crate_name) => { - sess.emit_err(NonAsciiName { span, crate_name }); + sess.emit_err(errors::NonAsciiName { span, crate_name }); } CrateError::ExternLocationNotExist(crate_name, loc) => { - sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc }); + sess.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc }); } CrateError::ExternLocationNotFile(crate_name, loc) => { - sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); + sess.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates }); + sess.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); } CrateError::SymbolConflictsCurrent(root_name) => { - sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); + sess.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); } CrateError::SymbolConflictsOthers(root_name) => { - sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name }); + sess.emit_err(errors::SymbolConflictsOthers { span, crate_name: root_name }); } CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - sess.emit_err(StableCrateIdCollision { span, crate_name0, crate_name1 }); + sess.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 }); } CrateError::DlOpen(s) | CrateError::DlSym(s) => { - sess.emit_err(DlError { span, err: s }); + sess.emit_err(errors::DlError { span, err: s }); } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; @@ -1012,8 +1007,12 @@ impl CrateError { if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name }); - sess.emit_err(LibFilenameForm { + sess.emit_err(errors::CrateLocationUnknownType { + span, + path: &path, + crate_name, + }); + sess.emit_err(errors::LibFilenameForm { span, dll_prefix: &locator.dll_prefix, dll_suffix: &locator.dll_suffix, @@ -1039,7 +1038,7 @@ impl CrateError { )); } } - sess.emit_err(NewerCrateVersion { + sess.emit_err(errors::NewerCrateVersion { span, crate_name: crate_name, add_info, @@ -1055,7 +1054,7 @@ impl CrateError { path.display(), )); } - sess.emit_err(NoCrateWithTriple { + sess.emit_err(errors::NoCrateWithTriple { span, crate_name, locator_triple: locator.triple.triple(), @@ -1071,7 +1070,12 @@ impl CrateError { path.display() )); } - sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates }); + sess.emit_err(errors::FoundStaticlib { + span, + crate_name, + add_info, + found_crates, + }); } else if !locator.crate_rejections.via_version.is_empty() { let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { @@ -1082,7 +1086,7 @@ impl CrateError { path.display(), )); } - sess.emit_err(IncompatibleRustc { + sess.emit_err(errors::IncompatibleRustc { span, crate_name, add_info, @@ -1094,14 +1098,14 @@ impl CrateError { for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { crate_rejections.push(got); } - sess.emit_err(InvalidMetadataFiles { + sess.emit_err(errors::InvalidMetadataFiles { span, crate_name, add_info, crate_rejections, }); } else { - sess.emit_err(CannotFindCrate { + sess.emit_err(errors::CannotFindCrate { span, crate_name, add_info, @@ -1118,7 +1122,7 @@ impl CrateError { } } CrateError::NonDylibPlugin(crate_name) => { - sess.emit_err(NoDylibPlugin { span, crate_name }); + sess.emit_err(errors::NoDylibPlugin { span, crate_name }); } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index a5910100786e..e263fc748353 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -13,17 +13,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; -use crate::errors::{ - AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, - FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, - IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, - LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, - LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs, - MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, - MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, - RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, - UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, -}; +use crate::errors; use std::path::PathBuf; @@ -52,7 +42,7 @@ pub fn find_native_static_library( } } - sess.emit_fatal(MissingNativeLibrary::new(name, verbatim)); + sess.emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)); } fn find_bundled_library( @@ -129,26 +119,26 @@ impl<'tcx> Collector<'tcx> { match item.name_or_empty() { sym::name => { if name.is_some() { - sess.emit_err(MultipleNamesInLink { span: item.span() }); + sess.emit_err(errors::MultipleNamesInLink { span: item.span() }); continue; } let Some(link_name) = item.value_str() else { - sess.emit_err(LinkNameForm { span: item.span() }); + sess.emit_err(errors::LinkNameForm { span: item.span() }); continue; }; let span = item.name_value_literal_span().unwrap(); if link_name.is_empty() { - sess.emit_err(EmptyLinkName { span }); + sess.emit_err(errors::EmptyLinkName { span }); } name = Some((link_name, span)); } sym::kind => { if kind.is_some() { - sess.emit_err(MultipleKindsInLink { span: item.span() }); + sess.emit_err(errors::MultipleKindsInLink { span: item.span() }); continue; } let Some(link_kind) = item.value_str() else { - sess.emit_err(LinkKindForm { span: item.span() }); + sess.emit_err(errors::LinkKindForm { span: item.span() }); continue; }; @@ -158,13 +148,13 @@ impl<'tcx> Collector<'tcx> { "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { if !sess.target.is_like_osx { - sess.emit_err(LinkFrameworkApple { span }); + sess.emit_err(errors::LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { if !sess.target.is_like_windows { - sess.emit_err(FrameworkOnlyWindows { span }); + sess.emit_err(errors::FrameworkOnlyWindows { span }); } else if !features.raw_dylib && sess.target.arch == "x86" { feature_err( &sess.parse_sess, @@ -177,7 +167,7 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::RawDylib } kind => { - sess.emit_err(UnknownLinkKind { span, kind }); + sess.emit_err(errors::UnknownLinkKind { span, kind }); continue; } }; @@ -185,26 +175,26 @@ impl<'tcx> Collector<'tcx> { } sym::modifiers => { if modifiers.is_some() { - sess.emit_err(MultipleLinkModifiers { span: item.span() }); + sess.emit_err(errors::MultipleLinkModifiers { span: item.span() }); continue; } let Some(link_modifiers) = item.value_str() else { - sess.emit_err(LinkModifiersForm { span: item.span() }); + sess.emit_err(errors::LinkModifiersForm { span: item.span() }); continue; }; modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); } sym::cfg => { if cfg.is_some() { - sess.emit_err(MultipleCfgs { span: item.span() }); + sess.emit_err(errors::MultipleCfgs { span: item.span() }); continue; } let Some(link_cfg) = item.meta_item_list() else { - sess.emit_err(LinkCfgForm { span: item.span() }); + sess.emit_err(errors::LinkCfgForm { span: item.span() }); continue; }; let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { - sess.emit_err(LinkCfgSinglePredicate { span: item.span() }); + sess.emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); continue; }; if !features.link_cfg { @@ -220,26 +210,26 @@ impl<'tcx> Collector<'tcx> { } sym::wasm_import_module => { if wasm_import_module.is_some() { - sess.emit_err(MultipleWasmImport { span: item.span() }); + sess.emit_err(errors::MultipleWasmImport { span: item.span() }); continue; } let Some(link_wasm_import_module) = item.value_str() else { - sess.emit_err(WasmImportForm { span: item.span() }); + sess.emit_err(errors::WasmImportForm { span: item.span() }); continue; }; wasm_import_module = Some((link_wasm_import_module, item.span())); } sym::import_name_type => { if import_name_type.is_some() { - sess.emit_err(MultipleImportNameType { span: item.span() }); + sess.emit_err(errors::MultipleImportNameType { span: item.span() }); continue; } let Some(link_import_name_type) = item.value_str() else { - sess.emit_err(ImportNameTypeForm { span: item.span() }); + sess.emit_err(errors::ImportNameTypeForm { span: item.span() }); continue; }; if self.tcx.sess.target.arch != "x86" { - sess.emit_err(ImportNameTypeX86 { span: item.span() }); + sess.emit_err(errors::ImportNameTypeX86 { span: item.span() }); continue; } @@ -248,7 +238,7 @@ impl<'tcx> Collector<'tcx> { "noprefix" => PeImportNameType::NoPrefix, "undecorated" => PeImportNameType::Undecorated, import_name_type => { - sess.emit_err(UnknownImportNameType { + sess.emit_err(errors::UnknownImportNameType { span: item.span(), import_name_type, }); @@ -268,7 +258,7 @@ impl<'tcx> Collector<'tcx> { import_name_type = Some((link_import_name_type, item.span())); } _ => { - sess.emit_err(UnexpectedLinkArg { span: item.span() }); + sess.emit_err(errors::UnexpectedLinkArg { span: item.span() }); } } } @@ -280,7 +270,7 @@ impl<'tcx> Collector<'tcx> { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { - sess.emit_err(InvalidLinkModifier { span }); + sess.emit_err(errors::InvalidLinkModifier { span }); continue; } }; @@ -298,7 +288,7 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { if dst.is_some() { - sess.emit_err(MultipleModifiers { span, modifier }); + sess.emit_err(errors::MultipleModifiers { span, modifier }); } else { *dst = Some(value); } @@ -308,7 +298,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(bundle) } ("bundle", _) => { - sess.emit_err(BundleNeedsStatic { span }); + sess.emit_err(errors::BundleNeedsStatic { span }); } ("verbatim", _) => assign_modifier(&mut verbatim), @@ -317,7 +307,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(whole_archive) } ("whole-archive", _) => { - sess.emit_err(WholeArchiveNeedsStatic { span }); + sess.emit_err(errors::WholeArchiveNeedsStatic { span }); } ("as-needed", Some(NativeLibKind::Dylib { as_needed })) @@ -326,11 +316,11 @@ impl<'tcx> Collector<'tcx> { assign_modifier(as_needed) } ("as-needed", _) => { - sess.emit_err(AsNeededCompatibility { span }); + sess.emit_err(errors::AsNeededCompatibility { span }); } _ => { - sess.emit_err(UnknownLinkModifier { span, modifier }); + sess.emit_err(errors::UnknownLinkModifier { span, modifier }); } } } @@ -338,23 +328,23 @@ impl<'tcx> Collector<'tcx> { if let Some((_, span)) = wasm_import_module { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { - sess.emit_err(IncompatibleWasmLink { span }); + sess.emit_err(errors::IncompatibleWasmLink { span }); } } else if name.is_none() { - sess.emit_err(LinkRequiresName { span: m.span }); + sess.emit_err(errors::LinkRequiresName { span: m.span }); } // Do this outside of the loop so that `import_name_type` can be specified before `kind`. if let Some((_, span)) = import_name_type { if kind != Some(NativeLibKind::RawDylib) { - sess.emit_err(ImportNameTypeRaw { span }); + sess.emit_err(errors::ImportNameTypeRaw { span }); } } let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.emit_err(RawDylibNoNul { span }); + sess.emit_err(errors::RawDylibNoNul { span }); } foreign_mod_items .iter() @@ -383,7 +373,9 @@ impl<'tcx> Collector<'tcx> { .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); - sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span }); + sess.emit_err(errors::LinkOrdinalRawDylib { + span: link_ordinal_attr.span, + }); } } @@ -414,7 +406,7 @@ impl<'tcx> Collector<'tcx> { for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx { // Cannot check this when parsing options because the target is not yet available. - self.tcx.sess.emit_err(LibFrameworkApple); + self.tcx.sess.emit_err(errors::LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self @@ -423,11 +415,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name }); + self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name }); + self.tcx.sess.emit_err(errors::RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name }); + self.tcx.sess.emit_err(errors::MultipleRenamings { lib_name: &lib.name }); } } } @@ -453,12 +445,15 @@ impl<'tcx> Collector<'tcx> { // explicit `:rename` in particular. if lib.has_modifiers() || passed_lib.has_modifiers() { match lib.foreign_module { - Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride { - span: Some(self.tcx.def_span(def_id)), - }), - None => { - self.tcx.sess.emit_err(NoLinkModOverride { span: None }) + Some(def_id) => { + self.tcx.sess.emit_err(errors::NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }) } + None => self + .tcx + .sess + .emit_err(errors::NoLinkModOverride { span: None }), }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -542,14 +537,14 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span }); + self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span }); } } } else { match abi { Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, _ => { - self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span }); + self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span }); } } }; From 3478b162f35650acc009cd6ce9919a6251e81a33 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 02:09:56 +0100 Subject: [PATCH 098/137] rustc_const_eval: remove huge error imports --- .../src/transform/check_consts/ops.rs | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 0cb5d2ff8c71..782a62accad9 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -22,13 +22,7 @@ use rustc_span::{BytePos, Pos, Span, Symbol}; use rustc_trait_selection::traits::SelectionContext; use super::ConstCx; -use crate::errors::{ - InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall, - NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr, - TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall, - UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw, - UnallowedOpInConstContext, UnstableConstFn, -}; +use crate::errors; use crate::util::{call_kind, CallDesugaringKind, CallKind}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -99,7 +93,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() }) + ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() }) } } @@ -303,10 +297,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span))); err } - _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => { - ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() }) - } - _ => ccx.tcx.sess.create_err(NonConstFnCall { + _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx + .tcx + .sess + .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }), + _ => ccx.tcx.sess.create_err(errors::NonConstFnCall { span, def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs), kind: ccx.const_kind(), @@ -351,7 +346,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { let mut err = ccx .tcx .sess - .create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) }); + .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) }); if ccx.is_const_stable_const_fn() { err.help("const-stable functions can only call other const-stable functions"); @@ -387,11 +382,11 @@ impl<'tcx> NonConstOp<'tcx> for Generator { let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind()); if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { ccx.tcx.sess.create_feature_err( - UnallowedOpInConstContext { span, msg }, + errors::UnallowedOpInConstContext { span, msg }, sym::const_async_blocks, ) } else { - ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg }) + ccx.tcx.sess.create_err(errors::UnallowedOpInConstContext { span, msg }) } } } @@ -404,7 +399,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(UnallowedHeapAllocations { + ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()), @@ -420,7 +415,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() }) + ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() }) } } @@ -471,7 +466,9 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell) + ccx.tcx + .sess + .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell) } } @@ -488,14 +485,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // FIXME: Maybe a more elegant solution to this if else case if let hir::ConstContext::Static(_) = ccx.const_kind() { - ccx.tcx.sess.create_err(InteriorMutableDataRefer { + ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer { span, opt_help: Some(()), kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()), }) } else { - ccx.tcx.sess.create_err(InteriorMutableDataRefer { + ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer { span, opt_help: None, kind: ccx.const_kind(), @@ -528,12 +525,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { match self.0 { - hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw { + hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()), }), - hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs { + hir::BorrowKind::Ref => ccx.tcx.sess.create_err(errors::UnallowedMutableRefs { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()), @@ -557,14 +554,14 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let kind = ccx.const_kind(); match self.0 { - hir::BorrowKind::Raw => ccx - .tcx - .sess - .create_feature_err(TransientMutBorrowErrRaw { span, kind }, sym::const_mut_refs), - hir::BorrowKind::Ref => ccx - .tcx - .sess - .create_feature_err(TransientMutBorrowErr { span, kind }, sym::const_mut_refs), + hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err( + errors::TransientMutBorrowErrRaw { span, kind }, + sym::const_mut_refs, + ), + hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err( + errors::TransientMutBorrowErr { span, kind }, + sym::const_mut_refs, + ), } } } @@ -586,9 +583,10 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx - .sess - .create_feature_err(MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs) + ccx.tcx.sess.create_feature_err( + errors::MutDerefErr { span, kind: ccx.const_kind() }, + sym::const_mut_refs, + ) } } @@ -601,7 +599,7 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(PanicNonStrErr { span }) + ccx.tcx.sess.create_err(errors::PanicNonStrErr { span }) } } @@ -652,7 +650,7 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(RawPtrToIntErr { span }) + ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span }) } } @@ -673,7 +671,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(StaticAccessErr { + ccx.tcx.sess.create_err(errors::StaticAccessErr { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()), @@ -690,7 +688,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - ccx.tcx.sess.create_err(NonConstOpErr { span }) + ccx.tcx.sess.create_err(errors::NonConstOpErr { span }) } } From a399f0ca8429db2399f007cdb12dad687b8973d9 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 02:49:50 +0100 Subject: [PATCH 099/137] rustc_passes: remove huge error imports --- compiler/rustc_passes/src/check_attr.rs | 68 +++++++++++++------------ compiler/rustc_passes/src/stability.rs | 45 ++++++++-------- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 644d701be0ca..238ec9ca30f7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -4,11 +4,7 @@ //! conflicts between multiple such attributes attached to the same //! item. -use crate::errors::{ - self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr, - OnlyHasEffectOn, ProcMacroDiffArguments, ProcMacroInvalidAbi, ProcMacroMissingArguments, - ProcMacroTypeError, ProcMacroUnsafe, TransparentIncompatible, UnrecognizedReprHint, -}; +use crate::errors; use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{fluent, Applicability, IntoDiagnosticArg, MultiSpan}; @@ -399,7 +395,7 @@ impl CheckAttrVisitor<'_> { UNUSED_ATTRIBUTES, hir_id, attr.span, - OnlyHasEffectOn { + errors::OnlyHasEffectOn { attr_name: attr.name_or_empty(), target_name: allowed_target.name().replace(' ', "_"), }, @@ -468,7 +464,7 @@ impl CheckAttrVisitor<'_> { ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(), ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(), }; - tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr }); + tcx.sess.emit_err(errors::ObjectLifetimeErr { span: p.span, repr }); } } } @@ -1715,7 +1711,7 @@ impl CheckAttrVisitor<'_> { match target { Target::Struct | Target::Union | Target::Enum => continue, _ => { - self.tcx.sess.emit_err(AttrApplication::StructEnumUnion { + self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion { hint_span: hint.span(), span, }); @@ -1736,16 +1732,18 @@ impl CheckAttrVisitor<'_> { match target { Target::Struct | Target::Union | Target::Enum | Target::Fn => continue, _ => { - self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion { - hint_span: hint.span(), - span, - }); + self.tcx.sess.emit_err( + errors::AttrApplication::StructEnumFunctionUnion { + hint_span: hint.span(), + span, + }, + ); } } } sym::packed => { if target != Target::Struct && target != Target::Union { - self.tcx.sess.emit_err(AttrApplication::StructUnion { + self.tcx.sess.emit_err(errors::AttrApplication::StructUnion { hint_span: hint.span(), span, }); @@ -1756,9 +1754,10 @@ impl CheckAttrVisitor<'_> { sym::simd => { is_simd = true; if target != Target::Struct { - self.tcx - .sess - .emit_err(AttrApplication::Struct { hint_span: hint.span(), span }); + self.tcx.sess.emit_err(errors::AttrApplication::Struct { + hint_span: hint.span(), + span, + }); } else { continue; } @@ -1768,7 +1767,7 @@ impl CheckAttrVisitor<'_> { match target { Target::Struct | Target::Union | Target::Enum => continue, _ => { - self.tcx.sess.emit_err(AttrApplication::StructEnumUnion { + self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion { hint_span: hint.span(), span, }); @@ -1789,15 +1788,16 @@ impl CheckAttrVisitor<'_> { | sym::usize => { int_reprs += 1; if target != Target::Enum { - self.tcx - .sess - .emit_err(AttrApplication::Enum { hint_span: hint.span(), span }); + self.tcx.sess.emit_err(errors::AttrApplication::Enum { + hint_span: hint.span(), + span, + }); } else { continue; } } _ => { - self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() }); + self.tcx.sess.emit_err(errors::UnrecognizedReprHint { span: hint.span() }); continue; } }; @@ -1810,9 +1810,10 @@ impl CheckAttrVisitor<'_> { // Error on repr(transparent, ). if is_transparent && hints.len() > 1 { let hint_spans: Vec<_> = hint_spans.clone().collect(); - self.tcx - .sess - .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() }); + self.tcx.sess.emit_err(errors::TransparentIncompatible { + hint_spans, + target: target.to_string(), + }); } // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8) if (int_reprs > 1) @@ -1965,7 +1966,7 @@ impl CheckAttrVisitor<'_> { match std::fs::File::open(&file) { Ok(_) => true, Err(error) => { - self.tcx.sess.emit_err(DebugVisualizerUnreadable { + self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable { span: meta_item.span, file: &file, error, @@ -2175,12 +2176,15 @@ impl CheckAttrVisitor<'_> { let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; if sig.abi != Abi::Rust { - tcx.sess.emit_err(ProcMacroInvalidAbi { span: hir_sig.span, abi: sig.abi.name() }); + tcx.sess.emit_err(errors::ProcMacroInvalidAbi { + span: hir_sig.span, + abi: sig.abi.name(), + }); self.abort.set(true); } if sig.unsafety == Unsafety::Unsafe { - tcx.sess.emit_err(ProcMacroUnsafe { span: hir_sig.span }); + tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span }); self.abort.set(true); } @@ -2188,7 +2192,7 @@ impl CheckAttrVisitor<'_> { // Typecheck the output if !drcx.types_may_unify(output, tokenstream) { - tcx.sess.emit_err(ProcMacroTypeError { + tcx.sess.emit_err(errors::ProcMacroTypeError { span: hir_sig.decl.output.span(), found: output, kind, @@ -2198,7 +2202,7 @@ impl CheckAttrVisitor<'_> { } if sig.inputs().len() < expected_input_count { - tcx.sess.emit_err(ProcMacroMissingArguments { + tcx.sess.emit_err(errors::ProcMacroMissingArguments { expected_input_count, span: hir_sig.span, kind, @@ -2213,7 +2217,7 @@ impl CheckAttrVisitor<'_> { sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count) { if !drcx.types_may_unify(*arg, tokenstream) { - tcx.sess.emit_err(ProcMacroTypeError { + tcx.sess.emit_err(errors::ProcMacroTypeError { span: input.span, found: *arg, kind, @@ -2228,7 +2232,7 @@ impl CheckAttrVisitor<'_> { let body_id = tcx.hir().body_owned_by(id.def_id); let excess = tcx.hir().body(body_id).params.get(expected_input_count..); if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess { - tcx.sess.emit_err(ProcMacroDiffArguments { + tcx.sess.emit_err(errors::ProcMacroDiffArguments { span: begin.span.to(end.span), count: excess.len(), kind, @@ -2378,7 +2382,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { if attr.style == AttrStyle::Inner { for attr_to_check in ATTRS_TO_CHECK { if attr.has_name(*attr_to_check) { - tcx.sess.emit_err(InvalidAttrAtCrateLevel { + tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel { span: attr.span, snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(), name: *attr_to_check, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 47911aef25d4..7299fc9705cc 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1,12 +1,7 @@ //! A pass that annotates every item and method with its stability level, //! propagating default levels lexically from parent to children ast nodes. -use crate::errors::{ - self, CannotStabilizeDeprecated, DeprecatedAttribute, DuplicateFeatureErr, - FeatureOnlyOnNightly, ImpliedFeatureNotExist, InvalidDeprecationVersion, InvalidStability, - MissingConstErr, MissingConstStabAttr, MissingStabilityAttr, TraitImplConstStable, - UnknownFeature, UselessStability, -}; +use crate::errors; use rustc_attr::{ self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable, UnstableReason, VERSION_PLACEHOLDER, @@ -185,7 +180,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { self.tcx .sess - .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span }); + .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span }); } } } @@ -203,7 +198,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr { if stab.is_none() { - self.tcx.sess.emit_err(DeprecatedAttribute { span: *span }); + self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span }); } } @@ -219,7 +214,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if kind == AnnotationKind::Prohibited || (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated) { - self.tcx.sess.emit_err(UselessStability { span, item_sp }); + self.tcx.sess.emit_err(errors::UselessStability { span, item_sp }); } debug!("annotate: found {:?}", stab); @@ -235,15 +230,16 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { match stab_v.parse::() { Err(_) => { - self.tcx.sess.emit_err(InvalidStability { span, item_sp }); + self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp }); break; } Ok(stab_vp) => match dep_v.parse::() { Ok(dep_vp) => match dep_vp.cmp(&stab_vp) { Ordering::Less => { - self.tcx - .sess - .emit_err(CannotStabilizeDeprecated { span, item_sp }); + self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated { + span, + item_sp, + }); break; } Ordering::Equal => continue, @@ -251,9 +247,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { }, Err(_) => { if dep_v != "TBD" { - self.tcx - .sess - .emit_err(InvalidDeprecationVersion { span, item_sp }); + self.tcx.sess.emit_err(errors::InvalidDeprecationVersion { + span, + item_sp, + }); } break; } @@ -527,7 +524,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { && self.effective_visibilities.is_reachable(def_id) { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); - self.tcx.sess.emit_err(MissingStabilityAttr { span, descr }); + self.tcx.sess.emit_err(errors::MissingStabilityAttr { span, descr }); } } @@ -555,7 +552,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { if is_const && is_stable && missing_const_stability_attribute && is_reachable { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); - self.tcx.sess.emit_err(MissingConstStabAttr { span, descr }); + self.tcx.sess.emit_err(errors::MissingConstStabAttr { span, descr }); } } } @@ -768,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { && *constness == hir::Constness::Const && const_stab.map_or(false, |(stab, _)| stab.is_const_stable()) { - self.tcx.sess.emit_err(TraitImplConstStable { span: item.span }); + self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span }); } } @@ -947,7 +944,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } if !lang_features.insert(feature) { // Warn if the user enables a lang feature multiple times. - tcx.sess.emit_err(DuplicateFeatureErr { span, feature }); + tcx.sess.emit_err(errors::DuplicateFeatureErr { span, feature }); } } @@ -955,14 +952,14 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let mut remaining_lib_features = FxIndexMap::default(); for (feature, span) in declared_lib_features { if !tcx.sess.opts.unstable_features.is_nightly_build() { - tcx.sess.emit_err(FeatureOnlyOnNightly { + tcx.sess.emit_err(errors::FeatureOnlyOnNightly { span: *span, release_channel: env!("CFG_RELEASE_CHANNEL"), }); } if remaining_lib_features.contains_key(&feature) { // Warn if the user enables a lib feature multiple times. - tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature }); + tcx.sess.emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature }); } remaining_lib_features.insert(feature, *span); } @@ -1063,7 +1060,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } for (feature, span) in remaining_lib_features { - tcx.sess.emit_err(UnknownFeature { span, feature: *feature }); + tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature }); } for (implied_by, feature) in remaining_implications { @@ -1074,7 +1071,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { .map(|(_, span)| span) .or_else(|| local_defined_features.unstable.get(&feature)) .expect("feature that implied another does not exist"); - tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by }); + tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by }); } // FIXME(#44232): the `used_features` table no longer exists, so we From b4a20abc489f5aa45b3aef17deec8e518d94153d Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 03:20:06 +0100 Subject: [PATCH 100/137] rustc_interface: remove huge error imports --- compiler/rustc_interface/src/passes.rs | 34 ++++++++++++-------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 60b60edd2c81..2a373ebc1324 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,9 +1,4 @@ -use crate::errors::{ - CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, - GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg, - TempsDirError, -}; +use crate::errors; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; @@ -374,15 +369,15 @@ pub fn configure_and_expand( if crate_types.len() > 1 { if is_executable_crate { - sess.emit_err(MixedBinCrate); + sess.emit_err(errors::MixedBinCrate); } if is_proc_macro_crate { - sess.emit_err(MixedProcMacroCrate); + sess.emit_err(errors::MixedProcMacroCrate); } } if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { - sess.emit_warning(ProcMacroCratePanicAbort); + sess.emit_warning(errors::ProcMacroCratePanicAbort); } // For backwards compatibility, we don't try to run proc macro injection @@ -392,7 +387,7 @@ pub fn configure_and_expand( // However, we do emit a warning, to let such users know that they should // start passing '--crate-type proc-macro' if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { - sess.emit_warning(ProcMacroDocWithoutArg); + sess.emit_warning(errors::ProcMacroDocWithoutArg); } else { krate = sess.time("maybe_create_a_macro_crate", || { let is_test_crate = sess.opts.test; @@ -441,9 +436,9 @@ pub fn configure_and_expand( spans.sort(); if ident == sym::ferris { let first_span = spans[0]; - sess.emit_err(FerrisIdentifier { spans, first_span }); + sess.emit_err(errors::FerrisIdentifier { spans, first_span }); } else { - sess.emit_err(EmojiIdentifier { spans, ident }); + sess.emit_err(errors::EmojiIdentifier { spans, ident }); } } }); @@ -655,7 +650,7 @@ fn write_out_deps( } } Err(error) => { - sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error }); + sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error }); } } } @@ -676,17 +671,20 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { if let Some(ref input_path) = sess.io.input.opt_path() { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { - sess.emit_fatal(InputFileWouldBeOverWritten { path: input_path }); + sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path }); } if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { - sess.emit_fatal(GeneratedFileConflictsWithDirectory { input_path, dir_path }); + sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory { + input_path, + dir_path, + }); } } } if let Some(ref dir) = sess.io.temps_dir { if fs::create_dir_all(dir).is_err() { - sess.emit_fatal(TempsDirError); + sess.emit_fatal(errors::TempsDirError); } } @@ -698,7 +696,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { if !only_dep_info { if let Some(ref dir) = sess.io.output_dir { if fs::create_dir_all(dir).is_err() { - sess.emit_fatal(OutDirError); + sess.emit_fatal(errors::OutDirError); } } } @@ -977,7 +975,7 @@ pub fn start_codegen<'tcx>( if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { - tcx.sess.emit_err(CantEmitMIR { error }); + tcx.sess.emit_err(errors::CantEmitMIR { error }); tcx.sess.abort_if_errors(); } } From 394fa192a94bf6fed793ac3f8ceacc7d35b55319 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 03:26:33 +0100 Subject: [PATCH 101/137] rustc_parse: remove huge error imports --- compiler/rustc_parse/src/parser/expr.rs | 186 +++++++++++------------- compiler/rustc_parse/src/parser/stmt.rs | 46 +++--- 2 files changed, 111 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 28347b137f37..473a5bb8cb8c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -5,26 +5,7 @@ use super::{ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken, }; -use crate::errors::{ - ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncBlockIn2015, - AsyncMoveOrderIncorrect, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, - ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg, - DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr, - ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, - FoundExprWouldBeStmt, HelpUseLatestEdition, IfExpressionLetSomeSub, - IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, - InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, - InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, - InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, - LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, - MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, - MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, - NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, - OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, - RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, - StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf, - UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, -}; +use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use core::mem; use rustc_ast::ptr::P; @@ -244,10 +225,10 @@ impl<'a> Parser<'a> { } .into(); let invalid = format!("{}=", &sugg); - self.sess.emit_err(InvalidComparisonOperator { + self.sess.emit_err(errors::InvalidComparisonOperator { span: sp, invalid: invalid.clone(), - sub: InvalidComparisonOperatorSub::Correctable { + sub: errors::InvalidComparisonOperatorSub::Correctable { span: sp, invalid, correct: sugg, @@ -262,10 +243,10 @@ impl<'a> Parser<'a> { && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); - self.sess.emit_err(InvalidComparisonOperator { + self.sess.emit_err(errors::InvalidComparisonOperator { span: sp, invalid: "<>".into(), - sub: InvalidComparisonOperatorSub::Correctable { + sub: errors::InvalidComparisonOperatorSub::Correctable { span: sp, invalid: "<>".into(), correct: "!=".into(), @@ -280,10 +261,10 @@ impl<'a> Parser<'a> { && self.prev_token.span.hi() == self.token.span.lo() { let sp = op.span.to(self.token.span); - self.sess.emit_err(InvalidComparisonOperator { + self.sess.emit_err(errors::InvalidComparisonOperator { span: sp, invalid: "<=>".into(), - sub: InvalidComparisonOperatorSub::Spaceship(sp), + sub: errors::InvalidComparisonOperatorSub::Spaceship(sp), }); self.bump(); } @@ -420,7 +401,7 @@ impl<'a> Parser<'a> { /// but the next token implies this should be parsed as an expression. /// For example: `if let Some(x) = x { x } else { 0 } / 2`. fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { - self.sess.emit_err(FoundExprWouldBeStmt { + self.sess.emit_err(errors::FoundExprWouldBeStmt { span: self.token.span, token: self.token.clone(), suggestion: ExprParenthesesNeeded::surrounding(lhs.span), @@ -447,18 +428,18 @@ impl<'a> Parser<'a> { } (Some(op), _) => (op, self.token.span), (None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => { - self.sess.emit_err(InvalidLogicalOperator { + self.sess.emit_err(errors::InvalidLogicalOperator { span: self.token.span, incorrect: "and".into(), - sub: InvalidLogicalOperatorSub::Conjunction(self.token.span), + sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span), }); (AssocOp::LAnd, span) } (None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => { - self.sess.emit_err(InvalidLogicalOperator { + self.sess.emit_err(errors::InvalidLogicalOperator { span: self.token.span, incorrect: "or".into(), - sub: InvalidLogicalOperatorSub::Disjunction(self.token.span), + sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span), }); (AssocOp::LOr, span) } @@ -581,8 +562,11 @@ impl<'a> Parser<'a> { } // `+lit` token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { - let mut err = - LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None }; + let mut err = errors::LeadingPlusNotSupported { + span: lo, + remove_plus: None, + add_parentheses: None, + }; // a block on the LHS might have been intended to be an expression instead if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { @@ -633,7 +617,7 @@ impl<'a> Parser<'a> { /// Recover on `~expr` in favor of `!expr`. fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - self.sess.emit_err(TildeAsUnaryOperator(lo)); + self.sess.emit_err(errors::TildeAsUnaryOperator(lo)); self.parse_unary_expr(lo, UnOp::Not) } @@ -661,14 +645,14 @@ impl<'a> Parser<'a> { let negated_token = self.look_ahead(1, |t| t.clone()); let sub_diag = if negated_token.is_numeric_lit() { - NotAsNegationOperatorSub::SuggestNotBitwise + errors::NotAsNegationOperatorSub::SuggestNotBitwise } else if negated_token.is_bool_lit() { - NotAsNegationOperatorSub::SuggestNotLogical + errors::NotAsNegationOperatorSub::SuggestNotLogical } else { - NotAsNegationOperatorSub::SuggestNotDefault + errors::NotAsNegationOperatorSub::SuggestNotDefault }; - self.sess.emit_err(NotAsNegationOperator { + self.sess.emit_err(errors::NotAsNegationOperator { negated: negated_token.span, negated_desc: super::token_descr(&negated_token), // Span the `not` plus trailing whitespace to avoid @@ -739,7 +723,7 @@ impl<'a> Parser<'a> { match self.parse_labeled_expr(label, false) { Ok(expr) => { type_err.cancel(); - self.sess.emit_err(MalformedLoopLabel { + self.sess.emit_err(errors::MalformedLoopLabel { span: label.ident.span, correct_label: label.ident, }); @@ -764,20 +748,22 @@ impl<'a> Parser<'a> { ); let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); - let suggestion = ComparisonOrShiftInterpretedAsGenericSugg { + let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg { left: expr.span.shrink_to_lo(), right: expr.span.shrink_to_hi(), }; match self.token.kind { - token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric { - comparison: self.token.span, - r#type: path, - args: args_span, - suggestion, - }), + token::Lt => { + self.sess.emit_err(errors::ComparisonInterpretedAsGeneric { + comparison: self.token.span, + r#type: path, + args: args_span, + suggestion, + }) + } token::BinOp(token::Shl) => { - self.sess.emit_err(ShiftInterpretedAsGeneric { + self.sess.emit_err(errors::ShiftInterpretedAsGeneric { shift: self.token.span, r#type: path, args: args_span, @@ -918,7 +904,7 @@ impl<'a> Parser<'a> { } fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) { - self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span }); + self.sess.emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span }); } /// Parse `mut?` or `raw [ const | mut ]`. @@ -1212,14 +1198,14 @@ impl<'a> Parser<'a> { let close_paren = self.prev_token.span; let span = lo.to(self.prev_token.span); if !fields.is_empty() { - let mut replacement_err = ParenthesesWithStructFields { + let mut replacement_err = errors::ParenthesesWithStructFields { span, r#type: path, - braces_for_struct: BracesForStructLiteral { + braces_for_struct: errors::BracesForStructLiteral { first: open_paren, second: close_paren, }, - no_fields_for_fn: NoFieldsForFnCall { + no_fields_for_fn: errors::NoFieldsForFnCall { fields: fields .into_iter() .map(|field| field.span.until(field.expr.span)) @@ -1286,7 +1272,7 @@ impl<'a> Parser<'a> { } else { // Field access `expr.f` if let Some(args) = seg.args { - self.sess.emit_err(FieldExpressionWithGeneric(args.span())); + self.sess.emit_err(errors::FieldExpressionWithGeneric(args.span())); } let span = lo.to(self.prev_token.span); @@ -1500,7 +1486,7 @@ impl<'a> Parser<'a> { let (span, kind) = if self.eat(&token::Not) { // MACRO INVOCATION expression if qself.is_some() { - self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span)); + self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); } let lo = path.span; let mac = P(MacCall { @@ -1550,7 +1536,7 @@ impl<'a> Parser<'a> { { let (lit, _) = self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| { - self_.sess.create_err(UnexpectedTokenAfterLabel { + self_.sess.create_err(errors::UnexpectedTokenAfterLabel { span: self_.token.span, remove_label: None, enclose_in_block: None, @@ -1562,7 +1548,7 @@ impl<'a> Parser<'a> { && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) { // We're probably inside of a `Path<'a>` that needs a turbofish - self.sess.emit_err(UnexpectedTokenAfterLabel { + self.sess.emit_err(errors::UnexpectedTokenAfterLabel { span: self.token.span, remove_label: None, enclose_in_block: None, @@ -1570,7 +1556,7 @@ impl<'a> Parser<'a> { consume_colon = false; Ok(self.mk_expr_err(lo)) } else { - let mut err = UnexpectedTokenAfterLabel { + let mut err = errors::UnexpectedTokenAfterLabel { span: self.token.span, remove_label: None, enclose_in_block: None, @@ -1606,7 +1592,7 @@ impl<'a> Parser<'a> { return expr; } - err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg { + err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg { left: span.shrink_to_lo(), right: span.shrink_to_hi(), }); @@ -1622,7 +1608,7 @@ impl<'a> Parser<'a> { }?; if !ate_colon && consume_colon { - self.sess.emit_err(RequireColonAfterLabeledExpression { + self.sess.emit_err(errors::RequireColonAfterLabeledExpression { span: expr.span, label: lo, label_end: lo.shrink_to_hi(), @@ -1671,7 +1657,7 @@ impl<'a> Parser<'a> { self.bump(); // `catch` let span = lo.to(self.prev_token.span); - self.sess.emit_err(DoCatchSyntaxRemoved { span }); + self.sess.emit_err(errors::DoCatchSyntaxRemoved { span }); self.parse_try_block(lo) } @@ -1719,9 +1705,9 @@ impl<'a> Parser<'a> { // The value expression can be a labeled loop, see issue #86948, e.g.: // `loop { break 'label: loop { break 'label 42; }; }` let lexpr = self.parse_labeled_expr(label, true)?; - self.sess.emit_err(LabeledLoopInBreak { + self.sess.emit_err(errors::LabeledLoopInBreak { span: lexpr.span, - sub: WrapExpressionInParentheses { + sub: errors::WrapExpressionInParentheses { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, @@ -1841,7 +1827,7 @@ impl<'a> Parser<'a> { }; if let Some(expr) = expr { if matches!(expr.kind, ExprKind::Err) { - let mut err = InvalidInterpolatedExpression { span: self.token.span } + let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } .into_diagnostic(&self.sess.span_diagnostic); err.downgrade_to_delayed_bug(); return Err(err); @@ -1902,7 +1888,7 @@ impl<'a> Parser<'a> { }); if let Some(token) = &recovered { self.bump(); - self.sess.emit_err(FloatLiteralRequiresIntegerPart { + self.sess.emit_err(errors::FloatLiteralRequiresIntegerPart { span: token.span, correct: pprust::token_to_string(token).into_owned(), }); @@ -1963,13 +1949,17 @@ impl<'a> Parser<'a> { if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) { // #59553: warn instead of reject out of hand to allow the fix to percolate // through the ecosystem when people fix their macros - self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex { + self.sess.emit_warning(errors::InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: Some(()), }); } else { - self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None }); + self.sess.emit_err(errors::InvalidLiteralSuffixOnTupleIndex { + span, + suffix, + exception: None, + }); } } @@ -2003,9 +1993,9 @@ impl<'a> Parser<'a> { let mut snapshot = self.create_snapshot_for_diagnostic(); match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) { Ok(arr) => { - self.sess.emit_err(ArrayBracketsInsteadOfSpaces { + self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces { span: arr.span, - sub: ArrayBracketsInsteadOfSpacesSugg { + sub: errors::ArrayBracketsInsteadOfSpacesSugg { left: lo, right: snapshot.prev_token.span, }, @@ -2051,7 +2041,7 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .map_or(false, |snippet| snippet == "]") => { - return Err(MissingSemicolonBeforeArray { + return Err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), }.into_diagnostic(&self.sess.span_diagnostic)); @@ -2077,7 +2067,7 @@ impl<'a> Parser<'a> { } if self.token.is_whole_block() { - self.sess.emit_err(InvalidBlockMacroSegment { + self.sess.emit_err(errors::InvalidBlockMacroSegment { span: self.token.span, context: lo.to(self.token.span), }); @@ -2181,7 +2171,7 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(AsyncMoveOrderIncorrect { span: move_async_span } + Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } .into_diagnostic(&self.sess.span_diagnostic)) } else { Ok(CaptureBy::Value) @@ -2259,17 +2249,17 @@ impl<'a> Parser<'a> { let block = match &mut cond.kind { ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) if let ExprKind::Block(_, None) = right.kind => { - self.sess.emit_err(IfExpressionMissingThenBlock { + self.sess.emit_err(errors::IfExpressionMissingThenBlock { if_span: lo, missing_then_block_sub: - IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), + errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), let_else_sub: None, }); std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) }, ExprKind::Block(_, None) => { - self.sess.emit_err(IfExpressionMissingCondition { + self.sess.emit_err(errors::IfExpressionMissingCondition { if_span: lo.shrink_to_hi(), block_span: self.sess.source_map().start_point(cond_span), }); @@ -2291,11 +2281,11 @@ impl<'a> Parser<'a> { block } else { let let_else_sub = matches!(cond.kind, ExprKind::Let(..)) - .then(|| IfExpressionLetSomeSub { if_span: lo.until(cond_span) }); + .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) }); - self.sess.emit_err(IfExpressionMissingThenBlock { + self.sess.emit_err(errors::IfExpressionMissingThenBlock { if_span: lo, - missing_then_block_sub: IfExpressionMissingThenBlockSub::AddThenBlock( + missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock( cond_span.shrink_to_hi(), ), let_else_sub, @@ -2351,7 +2341,7 @@ impl<'a> Parser<'a> { TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _) ); if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain { - self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span }); + self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span }); } self.bump(); // Eat `let` token @@ -2363,7 +2353,7 @@ impl<'a> Parser<'a> { CommaRecoveryMode::LikelyTuple, )?; if self.token == token::EqEq { - self.sess.emit_err(ExpectedEqForLetExpr { + self.sess.emit_err(errors::ExpectedEqForLetExpr { span: self.token.span, sugg_span: self.token.span, }); @@ -2398,7 +2388,7 @@ impl<'a> Parser<'a> { if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) && classify::expr_requires_semi_to_be_stmt(&cond) => { - self.sess.emit_err(ExpectedElseBlock { + self.sess.emit_err(errors::ExpectedElseBlock { first_tok_span, first_tok, else_span, @@ -2438,7 +2428,7 @@ impl<'a> Parser<'a> { [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span), }; let ctx = if is_ctx_else { "else" } else { "if" }; - self.sess.emit_err(OuterAttributeNotAllowedOnIfElse { + self.sess.emit_err(errors::OuterAttributeNotAllowedOnIfElse { last, branch_span, ctx_span, @@ -2451,7 +2441,7 @@ impl<'a> Parser<'a> { if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind && let BinOpKind::And = binop && let ExprKind::If(cond, ..) = &right.kind { - Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) + Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) } else { Ok(()) } @@ -2492,12 +2482,12 @@ impl<'a> Parser<'a> { // Possibly using JS syntax (#75311). let span = self.token.span; self.bump(); - (span, MissingInInForLoopSub::InNotOf) + (span, errors::MissingInInForLoopSub::InNotOf) } else { - (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn) + (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn) }; - self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) }); + self.sess.emit_err(errors::MissingInInForLoop { span, sub: sub(span) }); } /// Parses a `while` or `while let` expression (`while` token already eaten). @@ -2601,17 +2591,17 @@ impl<'a> Parser<'a> { let err = |this: &Parser<'_>, stmts: Vec| { let span = stmts[0].span.to(stmts[stmts.len() - 1].span); - this.sess.emit_err(MatchArmBodyWithoutBraces { + this.sess.emit_err(errors::MatchArmBodyWithoutBraces { statements: span, arrow: arrow_span, num_statements: stmts.len(), sub: if stmts.len() > 1 { - MatchArmBodyWithoutBracesSugg::AddBraces { + errors::MatchArmBodyWithoutBracesSugg::AddBraces { left: span.shrink_to_lo(), right: span.shrink_to_hi(), } } else { - MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } + errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } }, }); this.mk_expr_err(span) @@ -2802,7 +2792,7 @@ impl<'a> Parser<'a> { .is_ok(); if pattern_follows && snapshot.check(&TokenKind::FatArrow) { err.cancel(); - this.sess.emit_err(MissingCommaAfterMatchArm { + this.sess.emit_err(errors::MissingCommaAfterMatchArm { span: hi.shrink_to_hi(), }); return Ok(true); @@ -2834,7 +2824,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(CatchAfterTry { span: self.prev_token.span } + Err(errors::CatchAfterTry { span: self.prev_token.span } .into_diagnostic(&self.sess.span_diagnostic)) } else { let span = span_lo.to(body.span); @@ -2910,9 +2900,9 @@ impl<'a> Parser<'a> { let expr = self.parse_struct_expr(qself.clone(), path.clone(), true); if let (Ok(expr), false) = (&expr, struct_allowed) { // This is a struct literal, but we don't can't accept them here. - self.sess.emit_err(StructLiteralNotAllowedHere { + self.sess.emit_err(errors::StructLiteralNotAllowedHere { span: expr.span, - sub: StructLiteralNotAllowedHereSugg { + sub: errors::StructLiteralNotAllowedHereSugg { left: path.span.shrink_to_lo(), right: expr.span.shrink_to_hi(), }, @@ -2935,8 +2925,8 @@ impl<'a> Parser<'a> { let mut async_block_err = |e: &mut Diagnostic, span: Span| { recover_async = true; - AsyncBlockIn2015 { span }.add_to_diagnostic(e); - HelpUseLatestEdition::new().add_to_diagnostic(e); + errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e); + errors::HelpUseLatestEdition::new().add_to_diagnostic(e); }; while self.token != token::CloseDelim(close_delim) { @@ -3080,7 +3070,7 @@ impl<'a> Parser<'a> { if self.token != token::Comma { return; } - self.sess.emit_err(CommaAfterBaseStruct { + self.sess.emit_err(errors::CommaAfterBaseStruct { span: span.to(self.prev_token.span), comma: self.token.span, }); @@ -3093,7 +3083,7 @@ impl<'a> Parser<'a> { { // recover from typo of `...`, suggest `..` let span = self.prev_token.span; - self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span }); + self.sess.emit_err(errors::MissingDotDot { token_span: span, sugg_span: span }); return true; } false @@ -3161,18 +3151,18 @@ impl<'a> Parser<'a> { return; } - self.sess.emit_err(EqFieldInit { + self.sess.emit_err(errors::EqFieldInit { span: self.token.span, eq: field_name.span.shrink_to_hi().to(self.token.span), }); } fn err_dotdotdot_syntax(&self, span: Span) { - self.sess.emit_err(DotDotDot { span }); + self.sess.emit_err(errors::DotDotDot { span }); } fn err_larrow_operator(&self, span: Span) { - self.sess.emit_err(LeftArrowOperator { span }); + self.sess.emit_err(errors::LeftArrowOperator { span }); } fn mk_assign_op(&self, binop: BinOp, lhs: P, rhs: P) -> ExprKind { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 647639b9b62b..3afda5f69f0e 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -7,12 +7,7 @@ use super::TrailingToken; use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, }; -use crate::errors::{ - AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive, - DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse, - InvalidExpressionInLetElse, InvalidIdentiferStartsWithNumber, InvalidVariableDeclaration, - InvalidVariableDeclarationSub, WrapExpressionInParentheses, -}; +use crate::errors; use crate::maybe_whole; use rustc_ast as ast; @@ -64,29 +59,33 @@ impl<'a> Parser<'a> { if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) { self.bump(); let mut_let_span = lo.to(self.token.span); - self.sess.emit_err(InvalidVariableDeclaration { + self.sess.emit_err(errors::InvalidVariableDeclaration { span: mut_let_span, - sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span), + sub: errors::InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span), }); } Ok(Some(if self.token.is_keyword(kw::Let) { self.parse_local_mk(lo, attrs, capture_semi, force_collect)? } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { - self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)? + self.recover_stmt_local_after_let( + lo, + attrs, + errors::InvalidVariableDeclarationSub::MissingLet, + )? } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() { self.bump(); // `auto` self.recover_stmt_local_after_let( lo, attrs, - InvalidVariableDeclarationSub::UseLetNotAuto, + errors::InvalidVariableDeclarationSub::UseLetNotAuto, )? } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() { self.bump(); // `var` self.recover_stmt_local_after_let( lo, attrs, - InvalidVariableDeclarationSub::UseLetNotVar, + errors::InvalidVariableDeclarationSub::UseLetNotVar, )? } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, @@ -124,7 +123,7 @@ impl<'a> Parser<'a> { let bl = self.parse_block()?; // Destructuring assignment ... else. // This is not allowed, but point it out in a nice way. - self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) }); + self.sess.emit_err(errors::AssignmentElseNotAllowed { span: e.span.to(bl.span) }); } self.mk_stmt(lo.to(e.span), StmtKind::Expr(e)) } else { @@ -217,12 +216,12 @@ impl<'a> Parser<'a> { && let attrs = attrs.take_for_recovery(self.sess) && let attrs @ [.., last] = &*attrs { if last.is_doc_comment() { - self.sess.emit_err(DocCommentDoesNotDocumentAnything { + self.sess.emit_err(errors::DocCommentDoesNotDocumentAnything { span: last.span, missing_comma: None, }); } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { - self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span }); + self.sess.emit_err(errors::ExpectedStatementAfterOuterAttr { span: last.span }); } } } @@ -231,7 +230,7 @@ impl<'a> Parser<'a> { &mut self, lo: Span, attrs: AttrWrapper, - subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub, + subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub, ) -> PResult<'a, Stmt> { let stmt = self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| { @@ -242,7 +241,7 @@ impl<'a> Parser<'a> { TrailingToken::None, )) })?; - self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); + self.sess.emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); Ok(stmt) } @@ -270,7 +269,7 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) { - self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) }); + self.sess.emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) }); self.bump(); } @@ -373,7 +372,7 @@ impl<'a> Parser<'a> { rustc_ast::MetaItemLit::from_token(&self.token).is_none() && (lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) && self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) { - return Err(self.sess.create_err(InvalidIdentiferStartsWithNumber { span: self.token.span })); + return Err(self.sess.create_err(errors::InvalidIdentiferStartsWithNumber { span: self.token.span })); } Ok(()) } @@ -381,10 +380,10 @@ impl<'a> Parser<'a> { fn check_let_else_init_bool_expr(&self, init: &ast::Expr) { if let ast::ExprKind::Binary(op, ..) = init.kind { if op.node.lazy() { - self.sess.emit_err(InvalidExpressionInLetElse { + self.sess.emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.to_string(), - sugg: WrapExpressionInParentheses { + sugg: errors::WrapExpressionInParentheses { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), }, @@ -395,9 +394,9 @@ impl<'a> Parser<'a> { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - self.sess.emit_err(InvalidCurlyInLetElse { + self.sess.emit_err(errors::InvalidCurlyInLetElse { span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), - sugg: WrapExpressionInParentheses { + sugg: errors::WrapExpressionInParentheses { left: trailing.span.shrink_to_lo(), right: trailing.span.shrink_to_hi(), }, @@ -410,7 +409,8 @@ impl<'a> Parser<'a> { let eq_consumed = match self.token.kind { token::BinOpEq(..) => { // Recover `let x = 1` as `let x = 1` - self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span }); + self.sess + .emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span }); self.bump(); true } From 580cc89e9c36a89d3cc13a352c96f874eaa76581 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 5 Feb 2023 03:39:18 +0100 Subject: [PATCH 102/137] rustc_session: remove huge error imports --- compiler/rustc_session/src/session.rs | 52 ++++++++++++--------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index dbd419c1406f..8a0176f63917 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -3,15 +3,7 @@ use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use crate::config::Input; use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath}; -use crate::errors::{ - BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, - LinkerPluginToWindowsNotSupported, NotCircumventFeature, OptimisationFuelExhausted, - ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, SanitizerCfiEnabled, - SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks, - SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, - TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination, - UnsupportedDwarfVersion, -}; +use crate::errors; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; use crate::{filesearch, lint}; @@ -246,15 +238,15 @@ impl Session { if !unleashed_features.is_empty() { let mut must_err = false; // Create a diagnostic pointing at where things got unleashed. - self.emit_warning(SkippingConstChecks { + self.emit_warning(errors::SkippingConstChecks { unleashed_features: unleashed_features .iter() .map(|(span, gate)| { gate.map(|gate| { must_err = true; - UnleashedFeatureHelp::Named { span: *span, gate } + errors::UnleashedFeatureHelp::Named { span: *span, gate } }) - .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span }) + .unwrap_or(errors::UnleashedFeatureHelp::Unnamed { span: *span }) }) .collect(), }); @@ -262,7 +254,7 @@ impl Session { // If we should err, make sure we did. if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. - self.emit_err(NotCircumventFeature); + self.emit_err(errors::NotCircumventFeature); } } } @@ -901,7 +893,7 @@ impl Session { // We only call `msg` in case we can actually emit warnings. // Otherwise, this could cause a `delay_good_path_bug` to // trigger (issue #79546). - self.emit_warning(OptimisationFuelExhausted { msg: msg() }); + self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() }); } fuel.out_of_fuel = true; } else if fuel.remaining > 0 { @@ -1502,28 +1494,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) { && sess.opts.cg.prefer_dynamic && sess.target.is_like_windows { - sess.emit_err(LinkerPluginToWindowsNotSupported); + sess.emit_err(errors::LinkerPluginToWindowsNotSupported); } // Make sure that any given profiling data actually exists so LLVM can't // decide to silently skip PGO. if let Some(ref path) = sess.opts.cg.profile_use { if !path.exists() { - sess.emit_err(ProfileUseFileDoesNotExist { path }); + sess.emit_err(errors::ProfileUseFileDoesNotExist { path }); } } // Do the same for sample profile data. if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use { if !path.exists() { - sess.emit_err(ProfileSampleUseFileDoesNotExist { path }); + sess.emit_err(errors::ProfileSampleUseFileDoesNotExist { path }); } } // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { if sess.target.requires_uwtable && !include_uwtables { - sess.emit_err(TargetRequiresUnwindTables); + sess.emit_err(errors::TargetRequiresUnwindTables); } } @@ -1533,16 +1525,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) { match unsupported_sanitizers.into_iter().count() { 0 => {} 1 => { - sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() }); + sess.emit_err(errors::SanitizerNotSupported { us: unsupported_sanitizers.to_string() }); } _ => { - sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() }); + sess.emit_err(errors::SanitizersNotSupported { + us: unsupported_sanitizers.to_string(), + }); } } // Cannot mix and match sanitizers. let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter(); if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) { - sess.emit_err(CannotMixAndMatchSanitizers { + sess.emit_err(errors::CannotMixAndMatchSanitizers { first: first.to_string(), second: second.to_string(), }); @@ -1550,22 +1544,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Cannot enable crt-static with sanitizers on Linux if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() { - sess.emit_err(CannotEnableCrtStaticLinux); + sess.emit_err(errors::CannotEnableCrtStaticLinux); } // LLVM CFI and VFE both require LTO. if sess.lto() != config::Lto::Fat { if sess.is_sanitizer_cfi_enabled() { - sess.emit_err(SanitizerCfiEnabled); + sess.emit_err(errors::SanitizerCfiEnabled); } if sess.opts.unstable_opts.virtual_function_elimination { - sess.emit_err(UnstableVirtualFunctionElimination); + sess.emit_err(errors::UnstableVirtualFunctionElimination); } } // LLVM CFI and KCFI are mutually exclusive if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() { - sess.emit_err(CannotMixAndMatchSanitizers { + sess.emit_err(errors::CannotMixAndMatchSanitizers { first: "cfi".to_string(), second: "kcfi".to_string(), }); @@ -1573,7 +1567,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if sess.opts.unstable_opts.stack_protector != StackProtector::None { if !sess.target.options.supports_stack_protector { - sess.emit_warning(StackProtectorNotSupportedForTarget { + sess.emit_warning(errors::StackProtectorNotSupportedForTarget { stack_protector: sess.opts.unstable_opts.stack_protector, target_triple: &sess.opts.target_triple, }); @@ -1581,19 +1575,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" { - sess.emit_err(BranchProtectionRequiresAArch64); + sess.emit_err(errors::BranchProtectionRequiresAArch64); } if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { if dwarf_version > 5 { - sess.emit_err(UnsupportedDwarfVersion { dwarf_version }); + sess.emit_err(errors::UnsupportedDwarfVersion { dwarf_version }); } } if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo()) && !sess.opts.unstable_opts.unstable_options { - sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); + sess.emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } } From 32967296b444b639c965cbf126720c24decc9c65 Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Sat, 4 Feb 2023 20:13:16 -0800 Subject: [PATCH 103/137] Suggest null ptr if 0 is given as a raw ptr arg --- compiler/rustc_hir_typeck/src/demand.rs | 1 + .../src/fn_ctxt/suggestions.rs | 44 ++++++++++ tests/ui/suggest-null-ptr.fixed | 31 +++++++ tests/ui/suggest-null-ptr.rs | 31 +++++++ tests/ui/suggest-null-ptr.stderr | 83 +++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 tests/ui/suggest-null-ptr.fixed create mode 100644 tests/ui/suggest-null-ptr.rs create mode 100644 tests/ui/suggest-null-ptr.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 19b8fb96cde3..c4905a934cb4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_clone_for_ref(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected) + || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected) || self.note_result_coercion(err, expr, expected, expr_ty); if !suggested { self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 11d47053ade7..b03f0e94e100 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -13,6 +13,7 @@ use rustc_hir::{ use rustc_hir_analysis::astconv::AstConv; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty, TypeVisitable, @@ -1244,6 +1245,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they + /// pass in a literal 0 to an raw pointer. + #[instrument(skip(self, err))] + pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + expected_ty: Ty<'tcx>, + ) -> bool { + // Expected type needs to be a raw pointer. + let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else { + return false; + }; + + // Provided expression needs to be a literal `0`. + let ExprKind::Lit(Spanned { + node: rustc_ast::LitKind::Int(0, _), + span, + }) = expr.kind else { + return false; + }; + + // We need to find a null pointer symbol to suggest + let null_sym = match mutbl { + hir::Mutability::Not => sym::ptr_null, + hir::Mutability::Mut => sym::ptr_null_mut, + }; + let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else { + return false; + }; + let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did)); + + // We have satisfied all requirements to provide a suggestion. Emit it. + err.span_suggestion( + span, + format!("if you meant to create a null pointer, use `{null_path_str}()`"), + null_path_str + "()", + Applicability::MachineApplicable, + ); + + true + } + pub(crate) fn suggest_associated_const( &self, err: &mut Diagnostic, diff --git a/tests/ui/suggest-null-ptr.fixed b/tests/ui/suggest-null-ptr.fixed new file mode 100644 index 000000000000..40f900c7d30c --- /dev/null +++ b/tests/ui/suggest-null-ptr.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw +// pointer if a literal 0 was provided by the user. + +extern "C" { + fn foo(ptr: *const u8); + + fn foo_mut(ptr: *mut u8); + + fn usize(ptr: *const usize); + + fn usize_mut(ptr: *mut usize); +} + +fn main() { + unsafe { + foo(std::ptr::null()); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null()` + foo_mut(std::ptr::null_mut()); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + usize(std::ptr::null()); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null()` + usize_mut(std::ptr::null_mut()); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + } +} diff --git a/tests/ui/suggest-null-ptr.rs b/tests/ui/suggest-null-ptr.rs new file mode 100644 index 000000000000..19b595bf769e --- /dev/null +++ b/tests/ui/suggest-null-ptr.rs @@ -0,0 +1,31 @@ +// run-rustfix + +// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw +// pointer if a literal 0 was provided by the user. + +extern "C" { + fn foo(ptr: *const u8); + + fn foo_mut(ptr: *mut u8); + + fn usize(ptr: *const usize); + + fn usize_mut(ptr: *mut usize); +} + +fn main() { + unsafe { + foo(0); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null()` + foo_mut(0); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + usize(0); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null()` + usize_mut(0); + //~^ mismatched types [E0308] + //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + } +} diff --git a/tests/ui/suggest-null-ptr.stderr b/tests/ui/suggest-null-ptr.stderr new file mode 100644 index 000000000000..66a79d0749ee --- /dev/null +++ b/tests/ui/suggest-null-ptr.stderr @@ -0,0 +1,83 @@ +error[E0308]: mismatched types + --> $DIR/suggest-null-ptr.rs:18:13 + | +LL | foo(0); + | --- ^ expected `*const u8`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected raw pointer `*const u8` + found type `usize` +note: function defined here + --> $DIR/suggest-null-ptr.rs:7:8 + | +LL | fn foo(ptr: *const u8); + | ^^^ +help: if you meant to create a null pointer, use `std::ptr::null()` + | +LL | foo(std::ptr::null()); + | ~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-null-ptr.rs:21:17 + | +LL | foo_mut(0); + | ------- ^ expected `*mut u8`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected raw pointer `*mut u8` + found type `usize` +note: function defined here + --> $DIR/suggest-null-ptr.rs:9:8 + | +LL | fn foo_mut(ptr: *mut u8); + | ^^^^^^^ +help: if you meant to create a null pointer, use `std::ptr::null_mut()` + | +LL | foo_mut(std::ptr::null_mut()); + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-null-ptr.rs:24:15 + | +LL | usize(0); + | ----- ^ expected `*const usize`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected raw pointer `*const usize` + found type `usize` +note: function defined here + --> $DIR/suggest-null-ptr.rs:11:8 + | +LL | fn usize(ptr: *const usize); + | ^^^^^ +help: if you meant to create a null pointer, use `std::ptr::null()` + | +LL | usize(std::ptr::null()); + | ~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-null-ptr.rs:27:19 + | +LL | usize_mut(0); + | --------- ^ expected `*mut usize`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected raw pointer `*mut usize` + found type `usize` +note: function defined here + --> $DIR/suggest-null-ptr.rs:13:8 + | +LL | fn usize_mut(ptr: *mut usize); + | ^^^^^^^^^ +help: if you meant to create a null pointer, use `std::ptr::null_mut()` + | +LL | usize_mut(std::ptr::null_mut()); + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. From d85d906f8c44dd98bf6bc0e4b753aa241839c323 Mon Sep 17 00:00:00 2001 From: Boxy Date: Sun, 29 Jan 2023 01:00:57 +0000 Subject: [PATCH 104/137] emit `ConstEquate` in `TypeRelating` --- .../rustc_infer/src/infer/nll_relate/mod.rs | 13 ++++---- compiler/rustc_middle/src/ty/relate.rs | 30 +++++++++---------- .../const_kind_expr/relate_binop_arg_tys.rs | 18 +++++++++++ .../relate_binop_arg_tys.stderr | 20 +++++++++++++ .../const_kind_expr/relate_cast_arg_ty.rs | 12 ++++++++ .../const_kind_expr/relate_cast_arg_ty.stderr | 20 +++++++++++++ 6 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index f83219b8ee2a..a2cfe8d88816 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -817,12 +817,13 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { - fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) { - // We don't have to worry about the equality of consts during borrow checking - // as consts always have a static lifetime. - // FIXME(oli-obk): is this really true? We can at least have HKL and with - // inline consts we may have further lifetimes that may be unsound to treat as - // 'static. + fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { + self.delegate.register_obligations(vec![Obligation::new( + self.tcx(), + ObligationCause::dummy(), + self.param_env(), + ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)), + )]); } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index fa87301df7e7..890dabde1f73 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -629,6 +629,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( b = tcx.expand_abstract_consts(b); } + debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b); + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. @@ -665,30 +667,28 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical // exprs? Should we care about that? + // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to + // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought + // of as being generic over the argument types, however this is implicit so these types don't get + // related when we relate the substs of the item this const arg is for. let expr = match (ae, be) { - (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) - if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() => - { + (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => { + r.relate(al.ty(), bl.ty())?; + r.relate(ar.ty(), br.ty())?; Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?) } - (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) - if a_op == b_op && av.ty() == bv.ty() => - { + (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => { + r.relate(av.ty(), bv.ty())?; Expr::UnOp(a_op, r.consts(av, bv)?) } - (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) - if ak == bk && av.ty() == bv.ty() => - { + (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => { + r.relate(av.ty(), bv.ty())?; Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?) } (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba)) - if aa.len() == ba.len() - && af.ty() == bf.ty() - && aa - .iter() - .zip(ba.iter()) - .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) => + if aa.len() == ba.len() => { + r.relate(af.ty(), bf.ty())?; let func = r.consts(af, bf)?; let mut related_args = Vec::with_capacity(aa.len()); for (a_arg, b_arg) in aa.iter().zip(ba.iter()) { diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs new file mode 100644 index 000000000000..fd52fc355412 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs @@ -0,0 +1,18 @@ +// checks that when we relate a `Expr::Binop` we also relate the types of the +// const arguments. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Bar; + +const fn make_generic(_: usize, a: bool) -> bool { + a +} + +fn foo() -> Bar<{ make_generic(N, true == false) }> { + Bar::<{ make_generic(N, 1_u8 == 0_u8) }> + //~^ error: mismatched types + //~| error: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr new file mode 100644 index 000000000000..ba824e84a5ac --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/relate_binop_arg_tys.rs:13:5 + | +LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }` + | + = note: expected constant `{ make_generic(N, true == false) }` + found constant `{ make_generic(N, 1_u8 == 0_u8) }` + +error: unconstrained generic constant + --> $DIR/relate_binop_arg_tys.rs:13:11 + | +LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs new file mode 100644 index 000000000000..bef9d4b9e996 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs @@ -0,0 +1,12 @@ +// checks that when we relate a `Expr::Cast` we also relate the type of the +// const argument. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo() -> [(); (true as usize) + N] { + [(); (1_u8 as usize) + N] + //~^ error: mismatched types + //~| error: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr new file mode 100644 index 000000000000..d3ba870a2d7c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/relate_cast_arg_ty.rs:7:5 + | +LL | [(); (1_u8 as usize) + N] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N` + | + = note: expected constant `(true as usize) + N` + found constant `(1_u8 as usize) + N` + +error: unconstrained generic constant + --> $DIR/relate_cast_arg_ty.rs:7:10 + | +LL | [(); (1_u8 as usize) + N] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 0843acbea6441d5d4a07576ba206ccc01949662a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 4 Feb 2023 14:39:42 +0000 Subject: [PATCH 105/137] Fix SROA without deaggregation. --- compiler/rustc_mir_transform/src/sroa.rs | 129 +++++++++++------- .../const_debuginfo.main.ConstDebugInfo.diff | 30 ++-- ...variable_unprop_assign.main.ConstProp.diff | 41 +++--- ...es_into_variable.main.ConstProp.64bit.diff | 12 +- ...o_variable.main.PreCodegen.after.64bit.mir | 4 +- ...n.ScalarReplacementOfAggregates.64bit.diff | 16 ++- ....main.SimplifyLocals-final.after.64bit.mir | 4 +- ..._option_map_e2e.ezmap.PreCodegen.after.mir | 14 +- ...oa.flat.ScalarReplacementOfAggregates.diff | 37 ++++- ...structs.ScalarReplacementOfAggregates.diff | 16 ++- 10 files changed, 175 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 42124f5a4808..2118e3c55222 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -2,6 +2,7 @@ use crate::MirPass; use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -13,7 +14,9 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { sess.mir_opt_level() >= 3 } + #[instrument(level = "debug", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!(def_id = ?body.source.def_id()); let escaping = escaping_locals(&*body); debug!(?escaping); let replacements = compute_flattening(tcx, body, escaping); @@ -69,15 +72,28 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { self.super_rvalue(rvalue, location) } - fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - if let StatementKind::StorageLive(..) - | StatementKind::StorageDead(..) - | StatementKind::Deinit(..) = statement.kind - { - // Storage statements are expanded in run_pass. + fn visit_assign( + &mut self, + lvalue: &Place<'tcx>, + rvalue: &Rvalue<'tcx>, + location: Location, + ) { + if lvalue.as_local().is_some() && let Rvalue::Aggregate(..) = rvalue { + // Aggregate assignments are expanded in run_pass. + self.visit_rvalue(rvalue, location); return; } - self.super_statement(statement, location) + self.super_assign(lvalue, rvalue, location) + } + + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + match statement.kind { + // Storage statements are expanded in run_pass. + StatementKind::StorageLive(..) + | StatementKind::StorageDead(..) + | StatementKind::Deinit(..) => return, + _ => self.super_statement(statement, location), + } } fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { @@ -192,6 +208,7 @@ fn replace_flattened_locals<'tcx>( replacements, all_dead_locals, fragments, + patch: MirPatch::new(body), }; for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { visitor.visit_basic_block_data(bb, data); @@ -205,6 +222,7 @@ fn replace_flattened_locals<'tcx>( for var_debug_info in &mut body.var_debug_info { visitor.visit_var_debug_info(var_debug_info); } + visitor.patch.apply(body); } struct ReplacementVisitor<'tcx, 'll> { @@ -218,6 +236,7 @@ struct ReplacementVisitor<'tcx, 'll> { /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage /// and deinit statement and debuginfo. fragments: IndexVec], Local)>>, + patch: MirPatch<'tcx>, } impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { @@ -255,12 +274,63 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { - if let StatementKind::StorageLive(..) - | StatementKind::StorageDead(..) - | StatementKind::Deinit(..) = statement.kind - { - // Storage statements are expanded in run_pass. - return; + match statement.kind { + StatementKind::StorageLive(l) => { + if self.all_dead_locals.contains(l) { + let final_locals = &self.fragments[l]; + for &(_, fl) in final_locals { + self.patch.add_statement(location, StatementKind::StorageLive(fl)); + } + statement.make_nop(); + } + return; + } + StatementKind::StorageDead(l) => { + if self.all_dead_locals.contains(l) { + let final_locals = &self.fragments[l]; + for &(_, fl) in final_locals { + self.patch.add_statement(location, StatementKind::StorageDead(fl)); + } + statement.make_nop(); + } + return; + } + StatementKind::Deinit(box ref place) => { + if let Some(local) = place.as_local() + && self.all_dead_locals.contains(local) + { + let final_locals = &self.fragments[local]; + for &(_, fl) in final_locals { + self.patch.add_statement( + location, + StatementKind::Deinit(Box::new(fl.into())), + ); + } + statement.make_nop(); + return; + } + } + + StatementKind::Assign(box (ref place, Rvalue::Aggregate(_, ref operands))) => { + if let Some(local) = place.as_local() + && self.all_dead_locals.contains(local) + { + let final_locals = &self.fragments[local]; + for &(projection, fl) in final_locals { + let &[PlaceElem::Field(index, _)] = projection else { bug!() }; + let index = index.as_usize(); + let rvalue = Rvalue::Use(operands[index].clone()); + self.patch.add_statement( + location, + StatementKind::Assign(Box::new((fl.into(), rvalue))), + ); + } + statement.make_nop(); + return; + } + } + + _ => {} } self.super_statement(statement, location) } @@ -309,39 +379,6 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } } - fn visit_basic_block_data(&mut self, bb: BasicBlock, bbdata: &mut BasicBlockData<'tcx>) { - self.super_basic_block_data(bb, bbdata); - - #[derive(Debug)] - enum Stmt { - StorageLive, - StorageDead, - Deinit, - } - - bbdata.expand_statements(|stmt| { - let source_info = stmt.source_info; - let (stmt, origin_local) = match &stmt.kind { - StatementKind::StorageLive(l) => (Stmt::StorageLive, *l), - StatementKind::StorageDead(l) => (Stmt::StorageDead, *l), - StatementKind::Deinit(p) if let Some(l) = p.as_local() => (Stmt::Deinit, l), - _ => return None, - }; - if !self.all_dead_locals.contains(origin_local) { - return None; - } - let final_locals = self.fragments.get(origin_local)?; - Some(final_locals.iter().map(move |&(_, l)| { - let kind = match stmt { - Stmt::StorageLive => StatementKind::StorageLive(l), - Stmt::StorageDead => StatementKind::StorageDead(l), - Stmt::Deinit => StatementKind::Deinit(Box::new(l.into())), - }; - Statement { source_info, kind } - })) - }); - } - fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { assert!(!self.all_dead_locals.contains(*local)); } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 49e8b020dfb7..e14e586f34b0 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -8,8 +8,8 @@ let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16 let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20 let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24 - let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 - let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 + let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 + let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 scope 1 { - debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 + debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 @@ -35,12 +35,13 @@ let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 scope 7 { debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 - let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _15: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _16: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 scope 8 { - debug p => _12; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug p => Point{ .0 => _15, .1 => _16, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _12: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 scope 9 { -- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 +- debug a => _12; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 } } @@ -70,18 +71,11 @@ _10 = (const true, const false, const 123_u32); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 _11 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - _12 = Point { x: const 32_u32, y: const 32_u32 }; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 - StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - _14 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _15 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 - StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 + _15 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + _16 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + _12 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 + StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2 diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index a2e4890c6a64..8bd589fb2c87 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -4,18 +4,19 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + let mut _2: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 scope 1 { debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let mut _5: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let mut _6: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 scope 2 { - debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + debug x => (i32, i32){ .1 => _5, .0 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let _3: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 scope 3 { - debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 scope 4 { - debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug z => _6; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 } } } @@ -30,21 +31,17 @@ } bb1: { - StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 -- _2 = (const 1_i32, const 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 -+ _2 = const (1_i32, 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 - StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 -- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 -+ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 - StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + _5 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + _6 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _2 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _5 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 + StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + _3 = _5; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 } diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index 1368b114658d..691aa01a5640 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -17,7 +17,7 @@ debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { - debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } } } @@ -50,13 +50,7 @@ + _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir index 9db87cfc879b..81cfd22db6c5 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir @@ -3,12 +3,12 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 scope 2 { debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } @@ -18,8 +18,6 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff index de1d57ed401a..87271f24fc42 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff @@ -10,6 +10,7 @@ let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -45,10 +46,17 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 +- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 +- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _10 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _8 = _10; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 ++ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir index d926b9df7331..002e914e8fa1 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir @@ -3,12 +3,12 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 scope 2 { debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } @@ -18,8 +18,6 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 diff --git a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir index 5c898d798ff1..e338f15b4853 100644 --- a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir @@ -4,25 +4,22 @@ fn ezmap(_1: Option) -> Option { debug x => _1; // in scope 0 at $DIR/simple_option_map_e2e.rs:+0:14: +0:15 let mut _0: std::option::Option; // return place in scope 0 at $DIR/simple_option_map_e2e.rs:+0:33: +0:44 let mut _2: [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]; // in scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 - let mut _7: i32; // in scope 0 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 scope 1 (inlined map::) { // at $DIR/simple_option_map_e2e.rs:14:5: 14:22 debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20 debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34 let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16 let _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - let mut _6: (i32,); // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 scope 2 { debug x => _4; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - debug n => _7; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 + debug n => _4; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 } } } bb0: { StorageLive(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 - StorageLive(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22 _3 = discriminant(_1); // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map_e2e.rs:6:5: 6:14 } @@ -39,20 +36,13 @@ fn ezmap(_1: Option) -> Option { bb3: { _4 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - StorageLive(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - _6 = (move _4,); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - StorageLive(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - _7 = move (_6.0: i32); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - _5 = Add(_7, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 - StorageDead(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 - StorageDead(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:28: 7:29 + _5 = Add(_4, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 _0 = Option::::Some(move _5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 StorageDead(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2 } bb4: { - StorageDead(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22 StorageDead(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:21: +1:22 return; // scope 0 at $DIR/simple_option_map_e2e.rs:+2:2: +2:2 } diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff index 749c22c26e04..338ce262f1ec 100644 --- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff @@ -10,6 +10,10 @@ let mut _5: Foo; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 let mut _6: (); // in scope 0 at $DIR/sroa.rs:+1:45: +1:47 let mut _7: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:60: +1:68 ++ let mut _8: u8; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ let mut _9: (); // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ let mut _10: &str; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ let mut _11: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70 scope 1 { debug a => _1; // in scope 1 at $DIR/sroa.rs:+1:15: +1:16 debug b => _2; // in scope 1 at $DIR/sroa.rs:+1:18: +1:19 @@ -26,26 +30,45 @@ } bb0: { - StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 +- StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ StorageLive(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ StorageLive(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 _6 = (); // scope 0 at $DIR/sroa.rs:+1:45: +1:47 StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 _7 = Option::::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68 - _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 +- _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ _8 = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 // mir::Constant // + span: $DIR/sroa.rs:57:52: 57:55 // + literal: Const { ty: &str, val: Value(Slice(..)) } ++ _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 ++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 StorageDead(_7); // scope 0 at $DIR/sroa.rs:+1:69: +1:70 StorageDead(_6); // scope 0 at $DIR/sroa.rs:+1:69: +1:70 StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 - _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 +- _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16 ++ _1 = _8; // scope 0 at $DIR/sroa.rs:+1:15: +1:16 StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 - _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 +- _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19 ++ _2 = _9; // scope 0 at $DIR/sroa.rs:+1:18: +1:19 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 - _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 +- _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22 ++ _3 = _10; // scope 0 at $DIR/sroa.rs:+1:21: +1:22 StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 - _4 = (_5.3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 - StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 +- _4 = (_5.3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:24: +1:25 +- StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 ++ _4 = _11; // scope 0 at $DIR/sroa.rs:+1:24: +1:25 ++ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 ++ StorageDead(_9); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 ++ StorageDead(_10); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 ++ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+1:70: +1:71 ++ nop; // scope 0 at $DIR/sroa.rs:+1:70: +1:71 _0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +6:2 StorageDead(_4); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 diff --git a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff index dc4945104f4c..ca3cb3d8ed13 100644 --- a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff @@ -6,15 +6,23 @@ let mut _0: f32; // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:30 let mut _2: structs::U; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 let mut _3: f32; // in scope 0 at $DIR/sroa.rs:+6:18: +6:19 ++ let mut _4: f32; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 bb0: { - StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 +- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19 _3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19 - _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 +- _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ _4 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21 - _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23 - StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 +- _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23 +- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 ++ _0 = _4; // scope 0 at $DIR/sroa.rs:+6:5: +6:23 ++ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 ++ nop; // scope 0 at $DIR/sroa.rs:+7:1: +7:2 return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2 } } From dc4fe8e2953747605b085d297cf329824d499884 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 09:31:27 +0000 Subject: [PATCH 106/137] Make SROA expand assignments. --- compiler/rustc_mir_transform/src/sroa.rs | 88 ++++++++++++++----- ....copies.ScalarReplacementOfAggregates.diff | 48 ++++++++++ ...scaping.ScalarReplacementOfAggregates.diff | 4 +- ...oa.flat.ScalarReplacementOfAggregates.diff | 2 +- ..._copies.ScalarReplacementOfAggregates.diff | 48 ++++++++++ tests/mir-opt/sroa.rs | 30 +++++-- 6 files changed, 188 insertions(+), 32 deletions(-) create mode 100644 tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff create mode 100644 tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 2118e3c55222..f6609704d25d 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -78,10 +78,15 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { rvalue: &Rvalue<'tcx>, location: Location, ) { - if lvalue.as_local().is_some() && let Rvalue::Aggregate(..) = rvalue { - // Aggregate assignments are expanded in run_pass. - self.visit_rvalue(rvalue, location); - return; + if lvalue.as_local().is_some() { + match rvalue { + // Aggregate assignments are expanded in run_pass. + Rvalue::Aggregate(..) | Rvalue::Use(..) => { + self.visit_rvalue(rvalue, location); + return; + } + _ => {} + } } self.super_assign(lvalue, rvalue, location) } @@ -195,10 +200,9 @@ fn replace_flattened_locals<'tcx>( return; } - let mut fragments = IndexVec::new(); + let mut fragments = IndexVec::<_, Option>>::from_elem(None, &body.local_decls); for (k, v) in &replacements.fields { - fragments.ensure_contains_elem(k.local, || Vec::new()); - fragments[k.local].push((k.projection, *v)); + fragments[k.local].get_or_insert_default().push((k.projection, *v)); } debug!(?fragments); @@ -235,7 +239,7 @@ struct ReplacementVisitor<'tcx, 'll> { all_dead_locals: BitSet, /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage /// and deinit statement and debuginfo. - fragments: IndexVec], Local)>>, + fragments: IndexVec], Local)>>>, patch: MirPatch<'tcx>, } @@ -243,9 +247,9 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { fn gather_debug_info_fragments( &self, place: PlaceRef<'tcx>, - ) -> Vec> { + ) -> Option>> { let mut fragments = Vec::new(); - let parts = &self.fragments[place.local]; + let Some(parts) = &self.fragments[place.local] else { return None }; for (proj, replacement_local) in parts { if proj.starts_with(place.projection) { fragments.push(VarDebugInfoFragment { @@ -254,7 +258,7 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { }); } } - fragments + Some(fragments) } fn replace_place(&self, place: PlaceRef<'tcx>) -> Option> { @@ -276,8 +280,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { match statement.kind { StatementKind::StorageLive(l) => { - if self.all_dead_locals.contains(l) { - let final_locals = &self.fragments[l]; + if let Some(final_locals) = &self.fragments[l] { for &(_, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageLive(fl)); } @@ -286,8 +289,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { return; } StatementKind::StorageDead(l) => { - if self.all_dead_locals.contains(l) { - let final_locals = &self.fragments[l]; + if let Some(final_locals) = &self.fragments[l] { for &(_, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageDead(fl)); } @@ -297,9 +299,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } StatementKind::Deinit(box ref place) => { if let Some(local) = place.as_local() - && self.all_dead_locals.contains(local) + && let Some(final_locals) = &self.fragments[local] { - let final_locals = &self.fragments[local]; for &(_, fl) in final_locals { self.patch.add_statement( location, @@ -313,9 +314,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { StatementKind::Assign(box (ref place, Rvalue::Aggregate(_, ref operands))) => { if let Some(local) = place.as_local() - && self.all_dead_locals.contains(local) + && let Some(final_locals) = &self.fragments[local] { - let final_locals = &self.fragments[local]; for &(projection, fl) in final_locals { let &[PlaceElem::Field(index, _)] = projection else { bug!() }; let index = index.as_usize(); @@ -330,6 +330,48 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } } + StatementKind::Assign(box (ref place, Rvalue::Use(Operand::Constant(_)))) => { + if let Some(local) = place.as_local() + && let Some(final_locals) = &self.fragments[local] + { + for &(projection, fl) in final_locals { + let rvalue = Rvalue::Use(Operand::Move(place.project_deeper(projection, self.tcx))); + self.patch.add_statement( + location, + StatementKind::Assign(Box::new((fl.into(), rvalue))), + ); + } + self.all_dead_locals.remove(local); + return; + } + } + + StatementKind::Assign(box (ref lhs, Rvalue::Use(ref op))) => { + let (rplace, copy) = match op { + Operand::Copy(rplace) => (rplace, true), + Operand::Move(rplace) => (rplace, false), + Operand::Constant(_) => bug!(), + }; + if let Some(local) = lhs.as_local() + && let Some(final_locals) = &self.fragments[local] + { + for &(projection, fl) in final_locals { + let rplace = rplace.project_deeper(projection, self.tcx); + let rvalue = if copy { + Rvalue::Use(Operand::Copy(rplace)) + } else { + Rvalue::Use(Operand::Move(rplace)) + }; + self.patch.add_statement( + location, + StatementKind::Assign(Box::new((fl.into(), rvalue))), + ); + } + statement.make_nop(); + return; + } + } + _ => {} } self.super_statement(statement, location) @@ -348,9 +390,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { VarDebugInfoContents::Place(ref mut place) => { if let Some(repl) = self.replace_place(place.as_ref()) { *place = repl; - } else if self.all_dead_locals.contains(place.local) { + } else if let Some(fragments) = self.gather_debug_info_fragments(place.as_ref()) { let ty = place.ty(self.local_decls, self.tcx).ty; - let fragments = self.gather_debug_info_fragments(place.as_ref()); var_debug_info.value = VarDebugInfoContents::Composite { ty, fragments }; } } @@ -361,8 +402,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { if let Some(repl) = self.replace_place(fragment.contents.as_ref()) { fragment.contents = repl; true - } else if self.all_dead_locals.contains(fragment.contents.local) { - let frg = self.gather_debug_info_fragments(fragment.contents.as_ref()); + } else if let Some(frg) = + self.gather_debug_info_fragments(fragment.contents.as_ref()) + { new_fragments.extend(frg.into_iter().map(|mut f| { f.projection.splice(0..0, fragment.projection.iter().copied()); f diff --git a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff new file mode 100644 index 000000000000..72610de8eafa --- /dev/null +++ b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff @@ -0,0 +1,48 @@ +- // MIR for `copies` before ScalarReplacementOfAggregates ++ // MIR for `copies` after ScalarReplacementOfAggregates + + fn copies(_1: Foo) -> () { + debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:11: +0:12 + let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19 + let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _6: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 + scope 1 { +- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 ++ debug y => Foo{ .0 => _5, .2 => _6, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 + let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10 + scope 2 { + debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10 + let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10 + scope 3 { + debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10 + } + } + } + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 +- _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ _5 = (_1.0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ _6 = (_1.2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 + StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10 +- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 ++ _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16 + StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10 +- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 ++ _4 = _6; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 + _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +4:2 + StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2 + StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2 +- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2 + return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff index b01fb6fc9153..ea7f50072245 100644 --- a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff @@ -17,7 +17,7 @@ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:34: +2:37 _5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+2:34: +2:37 // mir::Constant - // + span: $DIR/sroa.rs:78:34: 78:35 + // + span: $DIR/sroa.rs:73:34: 73:35 // + literal: Const { ty: fn() -> u32 {g}, val: Value() } } @@ -28,7 +28,7 @@ _2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41 _1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+2:5: +2:42 // mir::Constant - // + span: $DIR/sroa.rs:78:5: 78:6 + // + span: $DIR/sroa.rs:73:5: 73:6 // + literal: Const { ty: fn(*const u32) {f}, val: Value() } } diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff index 338ce262f1ec..69631fc0213f 100644 --- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff @@ -45,7 +45,7 @@ + _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 + _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 // mir::Constant - // + span: $DIR/sroa.rs:57:52: 57:55 + // + span: $DIR/sroa.rs:53:52: 53:55 // + literal: Const { ty: &str, val: Value(Slice(..)) } + _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 + nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70 diff --git a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff new file mode 100644 index 000000000000..1a561a9edde3 --- /dev/null +++ b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff @@ -0,0 +1,48 @@ +- // MIR for `ref_copies` before ScalarReplacementOfAggregates ++ // MIR for `ref_copies` after ScalarReplacementOfAggregates + + fn ref_copies(_1: &Foo) -> () { + debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:15: +0:16 + let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:24: +0:24 + let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _6: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 + scope 1 { +- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 ++ debug y => Foo{ .0 => _5, .2 => _6, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 + let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10 + scope 2 { + debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10 + let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10 + scope 3 { + debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10 + } + } + } + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 +- _2 = (*_1); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ _5 = ((*_1).0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ _6 = ((*_1).2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:15 + StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10 +- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 ++ _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16 + StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10 +- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 ++ _4 = _6; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 + _0 = const (); // scope 0 at $DIR/sroa.rs:+0:24: +4:2 + StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2 + StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2 +- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2 + return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2 + } + } + diff --git a/tests/mir-opt/sroa.rs b/tests/mir-opt/sroa.rs index ff8deb40d7d5..b80f61600c26 100644 --- a/tests/mir-opt/sroa.rs +++ b/tests/mir-opt/sroa.rs @@ -12,17 +12,14 @@ impl Drop for Tag { fn drop(&mut self) {} } -// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff pub fn dropping() { S(Tag(0), Tag(1), Tag(2)).1; } -// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff pub fn enums(a: usize) -> usize { if let Some(a) = Some(a) { a } else { 0 } } -// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff pub fn structs(a: f32) -> f32 { struct U { _foo: usize, @@ -32,7 +29,6 @@ pub fn structs(a: f32) -> f32 { U { _foo: 0, a }.a } -// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff pub fn unions(a: f32) -> u32 { union Repr { f: f32, @@ -41,6 +37,7 @@ pub fn unions(a: f32) -> u32 { unsafe { Repr { f: a }.u } } +#[derive(Copy, Clone)] struct Foo { a: u8, b: (), @@ -52,7 +49,6 @@ fn g() -> u32 { 3 } -// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff pub fn flat() { let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) }; let _ = a; @@ -72,12 +68,23 @@ fn f(a: *const u32) { println!("{}", unsafe { *a.add(2) }); } -// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff pub fn escaping() { // Verify this struct is not flattened. f(&Escaping { a: 1, b: 2, c: g() }.a); } +fn copies(x: Foo) { + let y = x; + let t = y.a; + let u = y.c; +} + +fn ref_copies(x: &Foo) { + let y = *x; + let t = y.a; + let u = y.c; +} + fn main() { dropping(); enums(5); @@ -85,4 +92,15 @@ fn main() { unions(5.); flat(); escaping(); + copies(Foo { a: 5, b: (), c: "a", d: Some(-4) }); + ref_copies(&Foo { a: 5, b: (), c: "a", d: Some(-4) }); } + +// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.copies.ScalarReplacementOfAggregates.diff +// EMIT_MIR sroa.ref_copies.ScalarReplacementOfAggregates.diff From e465d647b1286e9127dab4df091315588b44dba9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 10:40:21 +0000 Subject: [PATCH 107/137] Introduce helper. --- compiler/rustc_mir_transform/src/sroa.rs | 47 ++++++++++++------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index f6609704d25d..462c3b4e9184 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -211,7 +211,7 @@ fn replace_flattened_locals<'tcx>( local_decls: &body.local_decls, replacements, all_dead_locals, - fragments, + fragments: &fragments, patch: MirPatch::new(body), }; for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { @@ -239,7 +239,7 @@ struct ReplacementVisitor<'tcx, 'll> { all_dead_locals: BitSet, /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage /// and deinit statement and debuginfo. - fragments: IndexVec], Local)>>>, + fragments: &'ll IndexVec], Local)>>>, patch: MirPatch<'tcx>, } @@ -270,6 +270,14 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { None } } + + fn place_fragments( + &self, + place: Place<'tcx>, + ) -> Option<&'ll Vec<(&'tcx [PlaceElem<'tcx>], Local)>> { + let local = place.as_local()?; + self.fragments[local].as_ref() + } } impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { @@ -297,25 +305,19 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } return; } - StatementKind::Deinit(box ref place) => { - if let Some(local) = place.as_local() - && let Some(final_locals) = &self.fragments[local] - { + StatementKind::Deinit(box place) => { + if let Some(final_locals) = self.place_fragments(place) { for &(_, fl) in final_locals { - self.patch.add_statement( - location, - StatementKind::Deinit(Box::new(fl.into())), - ); + self.patch + .add_statement(location, StatementKind::Deinit(Box::new(fl.into()))); } statement.make_nop(); return; } } - StatementKind::Assign(box (ref place, Rvalue::Aggregate(_, ref operands))) => { - if let Some(local) = place.as_local() - && let Some(final_locals) = &self.fragments[local] - { + StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref operands))) => { + if let Some(final_locals) = self.place_fragments(place) { for &(projection, fl) in final_locals { let &[PlaceElem::Field(index, _)] = projection else { bug!() }; let index = index.as_usize(); @@ -330,31 +332,28 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } } - StatementKind::Assign(box (ref place, Rvalue::Use(Operand::Constant(_)))) => { - if let Some(local) = place.as_local() - && let Some(final_locals) = &self.fragments[local] - { + StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => { + if let Some(final_locals) = self.place_fragments(place) { for &(projection, fl) in final_locals { - let rvalue = Rvalue::Use(Operand::Move(place.project_deeper(projection, self.tcx))); + let rvalue = + Rvalue::Use(Operand::Move(place.project_deeper(projection, self.tcx))); self.patch.add_statement( location, StatementKind::Assign(Box::new((fl.into(), rvalue))), ); } - self.all_dead_locals.remove(local); + self.all_dead_locals.remove(place.local); return; } } - StatementKind::Assign(box (ref lhs, Rvalue::Use(ref op))) => { + StatementKind::Assign(box (lhs, Rvalue::Use(ref op))) => { let (rplace, copy) = match op { Operand::Copy(rplace) => (rplace, true), Operand::Move(rplace) => (rplace, false), Operand::Constant(_) => bug!(), }; - if let Some(local) = lhs.as_local() - && let Some(final_locals) = &self.fragments[local] - { + if let Some(final_locals) = self.place_fragments(lhs) { for &(projection, fl) in final_locals { let rplace = rplace.project_deeper(projection, self.tcx); let rvalue = if copy { From 42c95146294c7773ca03e91e945fd545c6ce1ba2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 11:37:44 +0000 Subject: [PATCH 108/137] Simplify construction of replacement map. --- .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 158 ++++++++---------- .../const_debuginfo.main.ConstDebugInfo.diff | 52 +++--- ...ble_variable_aggregate.main.ConstProp.diff | 13 +- ...able_aggregate_mut_ref.main.ConstProp.diff | 10 +- ...variable_unprop_assign.main.ConstProp.diff | 16 +- ...n.ScalarReplacementOfAggregates.64bit.diff | 8 +- ....copies.ScalarReplacementOfAggregates.diff | 69 +++++--- ..._copies.ScalarReplacementOfAggregates.diff | 16 +- tests/mir-opt/sroa.rs | 2 + ...structs.ScalarReplacementOfAggregates.diff | 10 +- 11 files changed, 196 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 6bdbda909d7b..90d07c81256f 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -790,7 +790,7 @@ impl TryFrom> for TrackElem { } /// Invokes `f` on all direct fields of `ty`. -fn iter_fields<'tcx>( +pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, mut f: impl FnMut(Option, Field, Ty<'tcx>), diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 462c3b4e9184..3cfa0b16499a 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -1,11 +1,12 @@ use crate::MirPass; -use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; +use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::value_analysis::iter_fields; pub struct ScalarReplacementOfAggregates; @@ -125,6 +126,36 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { #[derive(Default, Debug)] struct ReplacementMap<'tcx> { fields: FxIndexMap, Local>, + /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage + /// and deinit statement and debuginfo. + fragments: IndexVec], Local)>>>, +} + +impl<'tcx> ReplacementMap<'tcx> { + fn gather_debug_info_fragments( + &self, + place: PlaceRef<'tcx>, + ) -> Option>> { + let mut fragments = Vec::new(); + let Some(parts) = &self.fragments[place.local] else { return None }; + for (proj, replacement_local) in parts { + if proj.starts_with(place.projection) { + fragments.push(VarDebugInfoFragment { + projection: proj[place.projection.len()..].to_vec(), + contents: Place::from(*replacement_local), + }); + } + } + Some(fragments) + } + + fn place_fragments( + &self, + place: Place<'tcx>, + ) -> Option<&Vec<(&'tcx [PlaceElem<'tcx>], Local)>> { + let local = place.as_local()?; + self.fragments[local].as_ref() + } } /// Compute the replacement of flattened places into locals. @@ -136,53 +167,30 @@ fn compute_flattening<'tcx>( body: &mut Body<'tcx>, escaping: BitSet, ) -> ReplacementMap<'tcx> { - let mut visitor = PreFlattenVisitor { - tcx, - escaping, - local_decls: &mut body.local_decls, - map: Default::default(), - }; - for (block, bbdata) in body.basic_blocks.iter_enumerated() { - visitor.visit_basic_block_data(block, bbdata); - } - return visitor.map; + let mut fields = FxIndexMap::default(); + let mut fragments = IndexVec::from_elem(None::>, &body.local_decls); - struct PreFlattenVisitor<'tcx, 'll> { - tcx: TyCtxt<'tcx>, - local_decls: &'ll mut LocalDecls<'tcx>, - escaping: BitSet, - map: ReplacementMap<'tcx>, - } - - impl<'tcx, 'll> PreFlattenVisitor<'tcx, 'll> { - fn create_place(&mut self, place: PlaceRef<'tcx>) { - if self.escaping.contains(place.local) { + for local in body.local_decls.indices() { + if escaping.contains(local) { + continue; + } + let decl = body.local_decls[local].clone(); + let ty = decl.ty; + iter_fields(ty, tcx, |variant, field, field_ty| { + if variant.is_some() { + // Downcasts are currently not supported. return; - } - - match self.map.fields.entry(place) { - IndexEntry::Occupied(_) => {} - IndexEntry::Vacant(v) => { - let ty = place.ty(&*self.local_decls, self.tcx).ty; - let local = self.local_decls.push(LocalDecl { - ty, - user_ty: None, - ..self.local_decls[place.local].clone() - }); - v.insert(local); - } - } - } - } - - impl<'tcx, 'll> Visitor<'tcx> for PreFlattenVisitor<'tcx, 'll> { - fn visit_place(&mut self, place: &Place<'tcx>, _: PlaceContext, _: Location) { - if let &[PlaceElem::Field(..), ..] = &place.projection[..] { - let pr = PlaceRef { local: place.local, projection: &place.projection[..1] }; - self.create_place(pr) - } - } + }; + let new_local = + body.local_decls.push(LocalDecl { ty: field_ty, user_ty: None, ..decl.clone() }); + let place = Place::from(local) + .project_deeper(&[PlaceElem::Field(field, field_ty)], tcx) + .as_ref(); + fields.insert(place, new_local); + fragments[local].get_or_insert_default().push((place.projection, new_local)); + }); } + ReplacementMap { fields, fragments } } /// Perform the replacement computed by `compute_flattening`. @@ -200,18 +208,11 @@ fn replace_flattened_locals<'tcx>( return; } - let mut fragments = IndexVec::<_, Option>>::from_elem(None, &body.local_decls); - for (k, v) in &replacements.fields { - fragments[k.local].get_or_insert_default().push((k.projection, *v)); - } - debug!(?fragments); - let mut visitor = ReplacementVisitor { tcx, local_decls: &body.local_decls, replacements, all_dead_locals, - fragments: &fragments, patch: MirPatch::new(body), }; for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { @@ -237,30 +238,10 @@ struct ReplacementVisitor<'tcx, 'll> { replacements: ReplacementMap<'tcx>, /// This is used to check that we are not leaving references to replaced locals behind. all_dead_locals: BitSet, - /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage - /// and deinit statement and debuginfo. - fragments: &'ll IndexVec], Local)>>>, patch: MirPatch<'tcx>, } impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { - fn gather_debug_info_fragments( - &self, - place: PlaceRef<'tcx>, - ) -> Option>> { - let mut fragments = Vec::new(); - let Some(parts) = &self.fragments[place.local] else { return None }; - for (proj, replacement_local) in parts { - if proj.starts_with(place.projection) { - fragments.push(VarDebugInfoFragment { - projection: proj[place.projection.len()..].to_vec(), - contents: Place::from(*replacement_local), - }); - } - } - Some(fragments) - } - fn replace_place(&self, place: PlaceRef<'tcx>) -> Option> { if let &[PlaceElem::Field(..), ref rest @ ..] = place.projection { let pr = PlaceRef { local: place.local, projection: &place.projection[..1] }; @@ -270,14 +251,6 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { None } } - - fn place_fragments( - &self, - place: Place<'tcx>, - ) -> Option<&'ll Vec<(&'tcx [PlaceElem<'tcx>], Local)>> { - let local = place.as_local()?; - self.fragments[local].as_ref() - } } impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { @@ -285,10 +258,11 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { self.tcx } + #[instrument(level = "trace", skip(self))] fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { match statement.kind { StatementKind::StorageLive(l) => { - if let Some(final_locals) = &self.fragments[l] { + if let Some(final_locals) = &self.replacements.fragments[l] { for &(_, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageLive(fl)); } @@ -297,7 +271,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { return; } StatementKind::StorageDead(l) => { - if let Some(final_locals) = &self.fragments[l] { + if let Some(final_locals) = &self.replacements.fragments[l] { for &(_, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageDead(fl)); } @@ -306,7 +280,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { return; } StatementKind::Deinit(box place) => { - if let Some(final_locals) = self.place_fragments(place) { + if let Some(final_locals) = self.replacements.place_fragments(place) { for &(_, fl) in final_locals { self.patch .add_statement(location, StatementKind::Deinit(Box::new(fl.into()))); @@ -317,7 +291,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref operands))) => { - if let Some(final_locals) = self.place_fragments(place) { + if let Some(final_locals) = self.replacements.place_fragments(place) { for &(projection, fl) in final_locals { let &[PlaceElem::Field(index, _)] = projection else { bug!() }; let index = index.as_usize(); @@ -333,7 +307,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => { - if let Some(final_locals) = self.place_fragments(place) { + if let Some(final_locals) = self.replacements.place_fragments(place) { for &(projection, fl) in final_locals { let rvalue = Rvalue::Use(Operand::Move(place.project_deeper(projection, self.tcx))); @@ -353,9 +327,12 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { Operand::Move(rplace) => (rplace, false), Operand::Constant(_) => bug!(), }; - if let Some(final_locals) = self.place_fragments(lhs) { + if let Some(final_locals) = self.replacements.place_fragments(lhs) { for &(projection, fl) in final_locals { let rplace = rplace.project_deeper(projection, self.tcx); + debug!(?rplace); + let rplace = self.replace_place(rplace.as_ref()).unwrap_or(rplace); + debug!(?rplace); let rvalue = if copy { Rvalue::Use(Operand::Copy(rplace)) } else { @@ -389,7 +366,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { VarDebugInfoContents::Place(ref mut place) => { if let Some(repl) = self.replace_place(place.as_ref()) { *place = repl; - } else if let Some(fragments) = self.gather_debug_info_fragments(place.as_ref()) { + } else if let Some(fragments) = + self.replacements.gather_debug_info_fragments(place.as_ref()) + { let ty = place.ty(self.local_decls, self.tcx).ty; var_debug_info.value = VarDebugInfoContents::Composite { ty, fragments }; } @@ -401,8 +380,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { if let Some(repl) = self.replace_place(fragment.contents.as_ref()) { fragment.contents = repl; true - } else if let Some(frg) = - self.gather_debug_info_fragments(fragment.contents.as_ref()) + } else if let Some(frg) = self + .replacements + .gather_debug_info_fragments(fragment.contents.as_ref()) { new_fragments.extend(frg.into_iter().map(|mut f| { f.projection.splice(0..0, fragment.projection.iter().copied()); diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index e14e586f34b0..f1f53a481655 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -8,8 +8,8 @@ let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16 let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20 let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24 - let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 - let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 + let mut _12: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 + let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 scope 1 { - debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 + debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 @@ -29,19 +29,21 @@ scope 5 { - debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 + debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 - let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _14: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _15: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _16: u32; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 scope 6 { - debug f => _10; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + debug f => (bool, bool, u32){ .0 => _14, .1 => _15, .2 => _16, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _10: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 scope 7 { - debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 - let _15: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _16: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + debug o => _10; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 + let _17: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _18: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 scope 8 { - debug p => Point{ .0 => _15, .1 => _16, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _12: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug p => Point{ .0 => _17, .1 => _18, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _11: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 scope 9 { -- debug a => _12; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 +- debug a => _11; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 } } @@ -67,17 +69,23 @@ // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 // + literal: Const { ty: &str, val: Value(Slice(..)) } - StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - _10 = (const true, const false, const 123_u32); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 - _11 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - _15 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - _16 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 - _12 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 - StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + _14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + _15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + _16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + _10 = Option::::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + _17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + _18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + _11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 + StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_16); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2 return; // scope 0 at $DIR/const_debuginfo.rs:+14:2: +14:2 diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index 0eb47087c9c7..37fbcf9dd496 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -6,9 +6,10 @@ let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 scope 1 { debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 - let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + let _3: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 scope 2 { - debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + debug y => (i32, i32){ .0 => _2, .1 => _3, }; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 } } @@ -18,9 +19,13 @@ + _1 = const (42_i32, 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 -- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 -+ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 + StorageLive(_3); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 +- _2 = (_1.0: i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 +- _3 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 ++ _2 = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 ++ _3 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 + StorageDead(_3); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index 26a1c3c1aa9e..134f0c080bf8 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -9,9 +9,10 @@ let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 scope 2 { debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 - let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + let _3: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + let _4: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 scope 3 { - debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + debug y => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 } } } @@ -23,8 +24,11 @@ _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19 ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 - _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + _3 = (_1.0: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 + _4 = (_1.1: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:2: +5:2 diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 8bd589fb2c87..4010dd6c6d0d 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -10,13 +10,13 @@ let mut _5: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 let mut _6: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 scope 2 { - debug x => (i32, i32){ .1 => _5, .0 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + debug x => (i32, i32){ .0 => _5, .1 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 let _3: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 scope 3 { debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 scope 4 { - debug z => _6; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 } } } @@ -31,17 +31,17 @@ } bb1: { - StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - _5 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - _6 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + _5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + _6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 _2 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _5 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 + _6 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - _3 = _5; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 + _3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 } diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff index 87271f24fc42..98cd020dade4 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff @@ -11,6 +11,7 @@ let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -51,11 +52,14 @@ - _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _10 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -+ _8 = _10; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 ++ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff index 72610de8eafa..b76e2d6d0f29 100644 --- a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff @@ -5,44 +5,65 @@ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:11: +0:12 let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19 let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ let _6: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 scope 1 { -- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 -+ debug y => Foo{ .0 => _5, .2 => _6, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 + debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10 scope 2 { debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10 let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10 scope 3 { debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10 + let _5: Foo; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ let _7: u8; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ let _8: (); // in scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ let _9: &str; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ let _10: std::option::Option; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10 + scope 4 { +- debug z => _5; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10 ++ debug z => Foo{ .0 => _7, .1 => _8, .2 => _9, .3 => _10, }; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10 + let _6: (); // in scope 4 at $DIR/sroa.rs:+5:9: +5:10 + scope 5 { + debug a => _6; // in scope 5 at $DIR/sroa.rs:+5:9: +5:10 + } + } } } } bb0: { -- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 -- _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 -+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ _5 = (_1.0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 -+ _6 = (_1.2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 -+ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 + StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 + _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10 -- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 -+ _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16 + _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10 -- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 -+ _4 = _6; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 - _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +4:2 - StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2 - StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2 -- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 -+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 -+ StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 -+ nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2 - return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2 + _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 +- StorageLive(_5); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 +- _5 = _2; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ StorageLive(_7); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ StorageLive(_8); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ StorageLive(_9); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ StorageLive(_10); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ nop; // scope 3 at $DIR/sroa.rs:+4:9: +4:10 ++ _7 = (_2.0: u8); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _8 = (_2.1: ()); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _9 = (_2.2: &str); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _10 = (_2.3: std::option::Option); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ nop; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 + StorageLive(_6); // scope 4 at $DIR/sroa.rs:+5:9: +5:10 +- _6 = (_5.1: ()); // scope 4 at $DIR/sroa.rs:+5:13: +5:16 ++ _6 = _8; // scope 4 at $DIR/sroa.rs:+5:13: +5:16 + _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +6:2 + StorageDead(_6); // scope 4 at $DIR/sroa.rs:+6:1: +6:2 +- StorageDead(_5); // scope 3 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_7); // scope 3 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_8); // scope 3 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_9); // scope 3 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_10); // scope 3 at $DIR/sroa.rs:+6:1: +6:2 ++ nop; // scope 3 at $DIR/sroa.rs:+6:1: +6:2 + StorageDead(_4); // scope 2 at $DIR/sroa.rs:+6:1: +6:2 + StorageDead(_3); // scope 1 at $DIR/sroa.rs:+6:1: +6:2 + StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 + return; // scope 0 at $DIR/sroa.rs:+6:2: +6:2 } } diff --git a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff index 1a561a9edde3..f0d62220dd66 100644 --- a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff @@ -6,10 +6,12 @@ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:24: +0:24 let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 + let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 -+ let _6: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _6: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _7: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _8: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 scope 1 { - debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 -+ debug y => Foo{ .0 => _5, .2 => _6, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 ++ debug y => Foo{ .0 => _5, .1 => _6, .2 => _7, .3 => _8, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10 scope 2 { debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10 @@ -25,22 +27,28 @@ - _2 = (*_1); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 + StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 + StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 + nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10 + _5 = ((*_1).0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 -+ _6 = ((*_1).2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ _6 = ((*_1).1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ _7 = ((*_1).2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 ++ _8 = ((*_1).3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:13: +1:15 + nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:15 StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10 - _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 + _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16 StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10 - _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 -+ _4 = _6; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 ++ _4 = _7; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 _0 = const (); // scope 0 at $DIR/sroa.rs:+0:24: +4:2 StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2 - StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 + StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 + StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_7); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 ++ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+4:1: +4:2 + nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2 return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2 } diff --git a/tests/mir-opt/sroa.rs b/tests/mir-opt/sroa.rs index b80f61600c26..471aac9f9d82 100644 --- a/tests/mir-opt/sroa.rs +++ b/tests/mir-opt/sroa.rs @@ -77,6 +77,8 @@ fn copies(x: Foo) { let y = x; let t = y.a; let u = y.c; + let z = y; + let a = z.b; } fn ref_copies(x: &Foo) { diff --git a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff index ca3cb3d8ed13..2c63d8b266dd 100644 --- a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff @@ -6,22 +6,26 @@ let mut _0: f32; // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:30 let mut _2: structs::U; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 let mut _3: f32; // in scope 0 at $DIR/sroa.rs:+6:18: +6:19 -+ let mut _4: f32; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ let mut _4: usize; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ let mut _5: f32; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21 bb0: { - StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 + StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21 + nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19 _3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19 - _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 -+ _4 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ _4 = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 ++ _5 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 + nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21 StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21 - _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23 - StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 -+ _0 = _4; // scope 0 at $DIR/sroa.rs:+6:5: +6:23 ++ _0 = _5; // scope 0 at $DIR/sroa.rs:+6:5: +6:23 + StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 ++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+7:1: +7:2 + nop; // scope 0 at $DIR/sroa.rs:+7:1: +7:2 return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2 } From 8e05ab04e54f2531198bb61c32ad2232d682a63c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 12:08:42 +0000 Subject: [PATCH 109/137] Run SROA to fixpoint. --- .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 74 +++++++++---------- ...ble_variable_aggregate.main.ConstProp.diff | 27 +++---- ....copies.ScalarReplacementOfAggregates.diff | 42 ++++++++--- 4 files changed, 78 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 90d07c81256f..8bf6493be4b0 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -824,7 +824,7 @@ pub fn iter_fields<'tcx>( } /// Returns all locals with projections that have their reference or address taken. -fn excluded_locals(body: &Body<'_>) -> IndexVec { +pub fn excluded_locals(body: &Body<'_>) -> IndexVec { struct Collector { result: IndexVec, } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 3cfa0b16499a..28963c77aa55 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::value_analysis::iter_fields; +use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; pub struct ScalarReplacementOfAggregates; @@ -18,26 +18,38 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { #[instrument(level = "debug", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let escaping = escaping_locals(&*body); - debug!(?escaping); - let replacements = compute_flattening(tcx, body, escaping); - debug!(?replacements); - replace_flattened_locals(tcx, body, replacements); + let mut excluded = excluded_locals(body); + loop { + debug!(?excluded); + let escaping = escaping_locals(&excluded, body); + debug!(?escaping); + let replacements = compute_flattening(tcx, body, escaping); + debug!(?replacements); + let all_dead_locals = replace_flattened_locals(tcx, body, replacements); + if !all_dead_locals.is_empty() && tcx.sess.mir_opt_level() >= 4 { + for local in excluded.indices() { + excluded[local] |= all_dead_locals.contains(local) ; + } + excluded.raw.resize(body.local_decls.len(), false); + } else { + break + } + } } } /// Identify all locals that are not eligible for SROA. /// /// There are 3 cases: -/// - the aggegated local is used or passed to other code (function parameters and arguments); +/// - the aggregated local is used or passed to other code (function parameters and arguments); /// - the locals is a union or an enum; /// - the local's address is taken, and thus the relative addresses of the fields are observable to /// client code. -fn escaping_locals(body: &Body<'_>) -> BitSet { +fn escaping_locals(excluded: &IndexVec, body: &Body<'_>) -> BitSet { let mut set = BitSet::new_empty(body.local_decls.len()); set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count)); for (local, decl) in body.local_decls().iter_enumerated() { - if decl.ty.is_union() || decl.ty.is_enum() { + if decl.ty.is_union() || decl.ty.is_enum() || excluded[local] { set.insert(local); } } @@ -62,17 +74,6 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { self.super_place(place, context, location); } - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - if let Rvalue::AddressOf(.., place) | Rvalue::Ref(.., place) = rvalue { - if !place.is_indirect() { - // Raw pointers may be used to access anything inside the enclosing place. - self.set.insert(place.local); - return; - } - } - self.super_rvalue(rvalue, location) - } - fn visit_assign( &mut self, lvalue: &Place<'tcx>, @@ -102,21 +103,6 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { } } - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - // Drop implicitly calls `drop_in_place`, which takes a `&mut`. - // This implies that `Drop` implicitly takes the address of the place. - if let TerminatorKind::Drop { place, .. } - | TerminatorKind::DropAndReplace { place, .. } = terminator.kind - { - if !place.is_indirect() { - // Raw pointers may be used to access anything inside the enclosing place. - self.set.insert(place.local); - return; - } - } - self.super_terminator(terminator, location); - } - // We ignore anything that happens in debuginfo, since we expand it using // `VarDebugInfoContents::Composite`. fn visit_var_debug_info(&mut self, _: &VarDebugInfo<'tcx>) {} @@ -198,14 +184,14 @@ fn replace_flattened_locals<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, replacements: ReplacementMap<'tcx>, -) { +) -> BitSet { let mut all_dead_locals = BitSet::new_empty(body.local_decls.len()); for p in replacements.fields.keys() { all_dead_locals.insert(p.local); } debug!(?all_dead_locals); if all_dead_locals.is_empty() { - return; + return all_dead_locals; } let mut visitor = ReplacementVisitor { @@ -227,7 +213,9 @@ fn replace_flattened_locals<'tcx>( for var_debug_info in &mut body.var_debug_info { visitor.visit_var_debug_info(var_debug_info); } - visitor.patch.apply(body); + let ReplacementVisitor { patch, all_dead_locals, .. } = visitor; + patch.apply(body); + all_dead_locals } struct ReplacementVisitor<'tcx, 'll> { @@ -361,6 +349,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } } + #[instrument(level = "trace", skip(self))] fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) { match &mut var_debug_info.value { VarDebugInfoContents::Place(ref mut place) => { @@ -375,11 +364,12 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } VarDebugInfoContents::Composite { ty: _, ref mut fragments } => { let mut new_fragments = Vec::new(); + debug!(?fragments); fragments .drain_filter(|fragment| { if let Some(repl) = self.replace_place(fragment.contents.as_ref()) { fragment.contents = repl; - true + false } else if let Some(frg) = self .replacements .gather_debug_info_fragments(fragment.contents.as_ref()) @@ -388,12 +378,14 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { f.projection.splice(0..0, fragment.projection.iter().copied()); f })); - false - } else { true + } else { + false } }) .for_each(drop); + debug!(?fragments); + debug!(?new_fragments); fragments.extend(new_fragments); } VarDebugInfoContents::Const(_) => {} diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index 37fbcf9dd496..d088c4f662b7 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -3,30 +3,27 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +0:11 - let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + let mut _3: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + let mut _4: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + debug x => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + let _1: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - let _3: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 scope 2 { - debug y => (i32, i32){ .0 => _2, .1 => _3, }; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + debug y => (i32, i32){ .0 => _3, .1 => _2, }; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 -- _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 -+ _1 = const (42_i32, 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 + StorageLive(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + _3 = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 + _4 = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 + _4 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - StorageLive(_3); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 -- _2 = (_1.0: i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 -- _3 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 -+ _2 = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 -+ _3 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 +- _2 = _4; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 ++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 - StorageDead(_3); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 + StorageDead(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 } } diff --git a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff index b76e2d6d0f29..976f6d44b752 100644 --- a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff @@ -5,8 +5,13 @@ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:11: +0:12 let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19 let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _11: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _12: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _13: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ let _14: std::option::Option; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10 scope 1 { - debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 +- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 ++ debug y => Foo{ .0 => _11, .1 => _12, .2 => _13, .3 => _14, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10 let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10 scope 2 { debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10 @@ -31,23 +36,35 @@ } bb0: { - StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 - _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 +- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 +- _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_12); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_13); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ StorageLive(_14); // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10 ++ _11 = (_1.0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ _12 = (_1.1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ _13 = (_1.2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ _14 = (_1.3: std::option::Option); // scope 0 at $DIR/sroa.rs:+1:13: +1:14 ++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:14 StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10 - _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 +- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16 ++ _3 = _11; // scope 1 at $DIR/sroa.rs:+2:13: +2:16 StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10 - _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 +- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16 - StorageLive(_5); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 - _5 = _2; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _4 = _13; // scope 2 at $DIR/sroa.rs:+3:13: +3:16 + StorageLive(_7); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 + StorageLive(_8); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 + StorageLive(_9); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 + StorageLive(_10); // scope 3 at $DIR/sroa.rs:+4:9: +4:10 + nop; // scope 3 at $DIR/sroa.rs:+4:9: +4:10 -+ _7 = (_2.0: u8); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 -+ _8 = (_2.1: ()); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 -+ _9 = (_2.2: &str); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 -+ _10 = (_2.3: std::option::Option); // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _7 = _11; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _8 = _12; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _9 = _13; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 ++ _10 = _14; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 + nop; // scope 3 at $DIR/sroa.rs:+4:13: +4:14 StorageLive(_6); // scope 4 at $DIR/sroa.rs:+5:9: +5:10 - _6 = (_5.1: ()); // scope 4 at $DIR/sroa.rs:+5:13: +5:16 @@ -62,7 +79,12 @@ + nop; // scope 3 at $DIR/sroa.rs:+6:1: +6:2 StorageDead(_4); // scope 2 at $DIR/sroa.rs:+6:1: +6:2 StorageDead(_3); // scope 1 at $DIR/sroa.rs:+6:1: +6:2 - StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 +- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_12); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_13); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 ++ StorageDead(_14); // scope 0 at $DIR/sroa.rs:+6:1: +6:2 ++ nop; // scope 0 at $DIR/sroa.rs:+6:1: +6:2 return; // scope 0 at $DIR/sroa.rs:+6:2: +6:2 } } From 29856180a8ba8e0d217d2df1bd4e8de0efe293f7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 13:35:33 +0000 Subject: [PATCH 110/137] Simplify ReplacementMap. --- compiler/rustc_mir_transform/src/sroa.rs | 193 +++++++++++++---------- 1 file changed, 109 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 28963c77aa55..26acd406ed8a 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -1,11 +1,10 @@ use crate::MirPass; -use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; pub struct ScalarReplacementOfAggregates; @@ -26,13 +25,13 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { let replacements = compute_flattening(tcx, body, escaping); debug!(?replacements); let all_dead_locals = replace_flattened_locals(tcx, body, replacements); - if !all_dead_locals.is_empty() && tcx.sess.mir_opt_level() >= 4 { + if !all_dead_locals.is_empty() { for local in excluded.indices() { - excluded[local] |= all_dead_locals.contains(local) ; + excluded[local] |= all_dead_locals.contains(local); } excluded.raw.resize(body.local_decls.len(), false); } else { - break + break; } } } @@ -111,36 +110,29 @@ fn escaping_locals(excluded: &IndexVec, body: &Body<'_>) -> BitSet< #[derive(Default, Debug)] struct ReplacementMap<'tcx> { - fields: FxIndexMap, Local>, /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage /// and deinit statement and debuginfo. - fragments: IndexVec], Local)>>>, + fragments: IndexVec, Local)>>>>, } impl<'tcx> ReplacementMap<'tcx> { - fn gather_debug_info_fragments( - &self, - place: PlaceRef<'tcx>, - ) -> Option>> { - let mut fragments = Vec::new(); - let Some(parts) = &self.fragments[place.local] else { return None }; - for (proj, replacement_local) in parts { - if proj.starts_with(place.projection) { - fragments.push(VarDebugInfoFragment { - projection: proj[place.projection.len()..].to_vec(), - contents: Place::from(*replacement_local), - }); - } - } - Some(fragments) + fn replace_place(&self, tcx: TyCtxt<'tcx>, place: PlaceRef<'tcx>) -> Option> { + let &[PlaceElem::Field(f, _), ref rest @ ..] = place.projection else { return None; }; + let fields = self.fragments[place.local].as_ref()?; + let (_, new_local) = fields[f]?; + Some(Place { local: new_local, projection: tcx.intern_place_elems(&rest) }) } fn place_fragments( &self, place: Place<'tcx>, - ) -> Option<&Vec<(&'tcx [PlaceElem<'tcx>], Local)>> { + ) -> Option, Local)> + '_> { let local = place.as_local()?; - self.fragments[local].as_ref() + let fields = self.fragments[local].as_ref()?; + Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)| { + let (ty, local) = opt_ty_local?; + Some((field, ty, local)) + })) } } @@ -153,8 +145,7 @@ fn compute_flattening<'tcx>( body: &mut Body<'tcx>, escaping: BitSet, ) -> ReplacementMap<'tcx> { - let mut fields = FxIndexMap::default(); - let mut fragments = IndexVec::from_elem(None::>, &body.local_decls); + let mut fragments = IndexVec::from_elem(None, &body.local_decls); for local in body.local_decls.indices() { if escaping.contains(local) { @@ -169,14 +160,10 @@ fn compute_flattening<'tcx>( }; let new_local = body.local_decls.push(LocalDecl { ty: field_ty, user_ty: None, ..decl.clone() }); - let place = Place::from(local) - .project_deeper(&[PlaceElem::Field(field, field_ty)], tcx) - .as_ref(); - fields.insert(place, new_local); - fragments[local].get_or_insert_default().push((place.projection, new_local)); + fragments.get_or_insert_with(local, IndexVec::new).insert(field, (field_ty, new_local)); }); } - ReplacementMap { fields, fragments } + ReplacementMap { fragments } } /// Perform the replacement computed by `compute_flattening`. @@ -186,8 +173,10 @@ fn replace_flattened_locals<'tcx>( replacements: ReplacementMap<'tcx>, ) -> BitSet { let mut all_dead_locals = BitSet::new_empty(body.local_decls.len()); - for p in replacements.fields.keys() { - all_dead_locals.insert(p.local); + for (local, replacements) in replacements.fragments.iter_enumerated() { + if replacements.is_some() { + all_dead_locals.insert(local); + } } debug!(?all_dead_locals); if all_dead_locals.is_empty() { @@ -197,7 +186,7 @@ fn replace_flattened_locals<'tcx>( let mut visitor = ReplacementVisitor { tcx, local_decls: &body.local_decls, - replacements, + replacements: &replacements, all_dead_locals, patch: MirPatch::new(body), }; @@ -223,21 +212,23 @@ struct ReplacementVisitor<'tcx, 'll> { /// This is only used to compute the type for `VarDebugInfoContents::Composite`. local_decls: &'ll LocalDecls<'tcx>, /// Work to do. - replacements: ReplacementMap<'tcx>, + replacements: &'ll ReplacementMap<'tcx>, /// This is used to check that we are not leaving references to replaced locals behind. all_dead_locals: BitSet, patch: MirPatch<'tcx>, } -impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> { - fn replace_place(&self, place: PlaceRef<'tcx>) -> Option> { - if let &[PlaceElem::Field(..), ref rest @ ..] = place.projection { - let pr = PlaceRef { local: place.local, projection: &place.projection[..1] }; - let local = self.replacements.fields.get(&pr)?; - Some(Place { local: *local, projection: self.tcx.intern_place_elems(&rest) }) - } else { - None +impl<'tcx> ReplacementVisitor<'tcx, '_> { + fn gather_debug_info_fragments(&self, local: Local) -> Option>> { + let mut fragments = Vec::new(); + let parts = self.replacements.place_fragments(local.into())?; + for (field, ty, replacement_local) in parts { + fragments.push(VarDebugInfoFragment { + projection: vec![PlaceElem::Field(field, ty)], + contents: Place::from(replacement_local), + }); } + Some(fragments) } } @@ -246,12 +237,21 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { self.tcx } + fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { + if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) { + *place = repl + } else { + self.super_place(place, context, location) + } + } + #[instrument(level = "trace", skip(self))] fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { match statement.kind { + // Duplicate storage and deinit statements, as they pretty much apply to all fields. StatementKind::StorageLive(l) => { - if let Some(final_locals) = &self.replacements.fragments[l] { - for &(_, fl) in final_locals { + if let Some(final_locals) = self.replacements.place_fragments(l.into()) { + for (_, _, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageLive(fl)); } statement.make_nop(); @@ -259,8 +259,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { return; } StatementKind::StorageDead(l) => { - if let Some(final_locals) = &self.replacements.fragments[l] { - for &(_, fl) in final_locals { + if let Some(final_locals) = self.replacements.place_fragments(l.into()) { + for (_, _, fl) in final_locals { self.patch.add_statement(location, StatementKind::StorageDead(fl)); } statement.make_nop(); @@ -269,7 +269,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } StatementKind::Deinit(box place) => { if let Some(final_locals) = self.replacements.place_fragments(place) { - for &(_, fl) in final_locals { + for (_, _, fl) in final_locals { self.patch .add_statement(location, StatementKind::Deinit(Box::new(fl.into()))); } @@ -278,48 +278,80 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { } } - StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref operands))) => { - if let Some(final_locals) = self.replacements.place_fragments(place) { - for &(projection, fl) in final_locals { - let &[PlaceElem::Field(index, _)] = projection else { bug!() }; - let index = index.as_usize(); - let rvalue = Rvalue::Use(operands[index].clone()); - self.patch.add_statement( - location, - StatementKind::Assign(Box::new((fl.into(), rvalue))), - ); + // We have `a = Struct { 0: x, 1: y, .. }`. + // We replace it by + // ``` + // a_0 = x + // a_1 = y + // ... + // ``` + StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref mut operands))) => { + if let Some(local) = place.as_local() + && let Some(final_locals) = &self.replacements.fragments[local] + { + // This is ok as we delete the statement later. + let operands = std::mem::take(operands); + for (&opt_ty_local, mut operand) in final_locals.iter().zip(operands) { + if let Some((_, new_local)) = opt_ty_local { + // Replace mentions of SROA'd locals that appear in the operand. + self.visit_operand(&mut operand, location); + + let rvalue = Rvalue::Use(operand); + self.patch.add_statement( + location, + StatementKind::Assign(Box::new((new_local.into(), rvalue))), + ); + } } statement.make_nop(); return; } } + // We have `a = some constant` + // We add the projections. + // ``` + // a_0 = a.0 + // a_1 = a.1 + // ... + // ``` + // ConstProp will pick up the pieces and replace them by actual constants. StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => { if let Some(final_locals) = self.replacements.place_fragments(place) { - for &(projection, fl) in final_locals { - let rvalue = - Rvalue::Use(Operand::Move(place.project_deeper(projection, self.tcx))); + for (field, ty, new_local) in final_locals { + let rplace = self.tcx.mk_place_field(place, field, ty); + let rvalue = Rvalue::Use(Operand::Move(rplace)); self.patch.add_statement( location, - StatementKind::Assign(Box::new((fl.into(), rvalue))), + StatementKind::Assign(Box::new((new_local.into(), rvalue))), ); } - self.all_dead_locals.remove(place.local); + // We still need `place.local` to exist, so don't make it nop. return; } } + // We have `a = move? place` + // We replace it by + // ``` + // a_0 = move? place.0 + // a_1 = move? place.1 + // ... + // ``` StatementKind::Assign(box (lhs, Rvalue::Use(ref op))) => { - let (rplace, copy) = match op { + let (rplace, copy) = match *op { Operand::Copy(rplace) => (rplace, true), Operand::Move(rplace) => (rplace, false), Operand::Constant(_) => bug!(), }; if let Some(final_locals) = self.replacements.place_fragments(lhs) { - for &(projection, fl) in final_locals { - let rplace = rplace.project_deeper(projection, self.tcx); + for (field, ty, new_local) in final_locals { + let rplace = self.tcx.mk_place_field(rplace, field, ty); debug!(?rplace); - let rplace = self.replace_place(rplace.as_ref()).unwrap_or(rplace); + let rplace = self + .replacements + .replace_place(self.tcx, rplace.as_ref()) + .unwrap_or(rplace); debug!(?rplace); let rvalue = if copy { Rvalue::Use(Operand::Copy(rplace)) @@ -328,7 +360,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { }; self.patch.add_statement( location, - StatementKind::Assign(Box::new((fl.into(), rvalue))), + StatementKind::Assign(Box::new((new_local.into(), rvalue))), ); } statement.make_nop(); @@ -341,22 +373,14 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { self.super_statement(statement, location) } - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if let Some(repl) = self.replace_place(place.as_ref()) { - *place = repl - } else { - self.super_place(place, context, location) - } - } - #[instrument(level = "trace", skip(self))] fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) { match &mut var_debug_info.value { VarDebugInfoContents::Place(ref mut place) => { - if let Some(repl) = self.replace_place(place.as_ref()) { + if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) { *place = repl; - } else if let Some(fragments) = - self.replacements.gather_debug_info_fragments(place.as_ref()) + } else if let Some(local) = place.as_local() + && let Some(fragments) = self.gather_debug_info_fragments(local) { let ty = place.ty(self.local_decls, self.tcx).ty; var_debug_info.value = VarDebugInfoContents::Composite { ty, fragments }; @@ -367,12 +391,13 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { debug!(?fragments); fragments .drain_filter(|fragment| { - if let Some(repl) = self.replace_place(fragment.contents.as_ref()) { + if let Some(repl) = + self.replacements.replace_place(self.tcx, fragment.contents.as_ref()) + { fragment.contents = repl; false - } else if let Some(frg) = self - .replacements - .gather_debug_info_fragments(fragment.contents.as_ref()) + } else if let Some(local) = fragment.contents.as_local() + && let Some(frg) = self.gather_debug_info_fragments(local) { new_fragments.extend(frg.into_iter().map(|mut f| { f.projection.splice(0..0, fragment.projection.iter().copied()); From 51ef82d19ba97fd60d13d02f708fd0eb43617cc7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 5 Feb 2023 13:51:37 +0000 Subject: [PATCH 111/137] Bless 32bit tests. --- ...es_into_variable.main.ConstProp.32bit.diff | 12 +++-------- ...o_variable.main.PreCodegen.after.32bit.mir | 4 +--- ...n.ScalarReplacementOfAggregates.32bit.diff | 20 +++++++++++++++---- ....main.SimplifyLocals-final.after.32bit.mir | 4 +--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index 1368b114658d..691aa01a5640 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -17,7 +17,7 @@ debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { - debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } } } @@ -50,13 +50,7 @@ + _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir index 9db87cfc879b..81cfd22db6c5 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir @@ -3,12 +3,12 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 scope 2 { debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } @@ -18,8 +18,6 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff index de1d57ed401a..98cd020dade4 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff @@ -10,6 +10,8 @@ let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -45,10 +47,20 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 +- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 +- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 ++ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 ++ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 ++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir index d926b9df7331..002e914e8fa1 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir +++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir @@ -3,12 +3,12 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 scope 2 { debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 scope 3 { debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 } @@ -18,8 +18,6 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 From 8cc5aa561cea5242fbf5834acf11e1e6e8f379fc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 26 Jan 2023 18:23:14 +0400 Subject: [PATCH 112/137] rustc_metadata: Refactor lazy table reading/writing Change wording from "nullable" to "default". Introduce a trait `IsDefault` for detecting values that are encoded as zeros or not encoded at all. Add panics to impossible cases. Some other minor cleanups. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 100 ++++++++-------- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- compiler/rustc_metadata/src/rmeta/table.rs | 113 +++++++++++++------ 3 files changed, 127 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9d8f14058f68..0533aacbd2fa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -365,26 +365,26 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { } } -// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ { let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.set($def_id.index, lazy); + $self.$tables.$table.set_some($def_id.index, lazy); } }}; } -// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ { let value = $value; let lazy = $self.lazy_array(value); - $self.$tables.$table.set($def_id.index, lazy); + $self.$tables.$table.set_some($def_id.index, lazy); } }}; } @@ -467,14 +467,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { { let def_key = self.lazy(table.def_key(def_index)); let def_path_hash = table.def_path_hash(def_index); - self.tables.def_keys.set(def_index, def_key); - self.tables.def_path_hashes.set(def_index, def_path_hash); + self.tables.def_keys.set_some(def_index, def_key); + self.tables.def_path_hashes.set_some(def_index, def_path_hash); } } else { for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() { let def_key = self.lazy(def_key); - self.tables.def_keys.set(def_index, def_key); - self.tables.def_path_hashes.set(def_index, *def_path_hash); + self.tables.def_keys.set_some(def_index, def_key); + self.tables.def_path_hashes.set_some(def_index, *def_path_hash); } } } @@ -548,7 +548,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let on_disk_index: u32 = on_disk_index.try_into().expect("cannot export more than U32_MAX files"); - adapted.set(on_disk_index, self.lazy(source_file)); + adapted.set_some(on_disk_index, self.lazy(source_file)); } adapted.encode(&mut self.opaque) @@ -1147,9 +1147,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if state.is_doc_hidden { attr_flags |= AttrFlags::IS_DOC_HIDDEN; } - if !attr_flags.is_empty() { - self.tables.attr_flags.set_nullable(def_id.local_def_index, attr_flags); - } + self.tables.attr_flags.set(def_id.local_def_index, attr_flags); } fn encode_def_ids(&mut self) { @@ -1161,7 +1159,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = local_id.to_def_id(); let def_kind = tcx.opt_def_kind(local_id); let Some(def_kind) = def_kind else { continue }; - self.tables.opt_def_kind.set(def_id.index, def_kind); + self.tables.opt_def_kind.set_some(def_id.index, def_kind); let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); self.encode_attrs(local_id); @@ -1264,14 +1262,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[variant.def_id] <- data); - self.tables.constness.set(variant.def_id.index, hir::Constness::Const); + self.tables.constness.set_some(variant.def_id.index, hir::Constness::Const); record_array!(self.tables.children[variant.def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })); if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor { - self.tables.constness.set(ctor_def_id.index, hir::Constness::Const); + self.tables.constness.set_some(ctor_def_id.index, hir::Constness::Const); let fn_sig = tcx.fn_sig(ctor_def_id); record!(self.tables.fn_sig[ctor_def_id] <- fn_sig); // FIXME only encode signature for ctor_def_id @@ -1342,16 +1340,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let impl_defaultness = tcx.impl_defaultness(def_id.expect_local()); - self.tables.impl_defaultness.set(def_id.index, impl_defaultness); + self.tables.impl_defaultness.set_some(def_id.index, impl_defaultness); let trait_item = tcx.associated_item(def_id); - self.tables.assoc_container.set(def_id.index, trait_item.container); + self.tables.assoc_container.set_some(def_id.index, trait_item.container); match trait_item.kind { ty::AssocKind::Const => {} ty::AssocKind::Fn => { record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id)); - self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id)); - self.tables.constness.set(def_id.index, hir::Constness::NotConst); + self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id)); + self.tables.constness.set_some(def_id.index, hir::Constness::NotConst); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); @@ -1367,14 +1365,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); - self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness); + self.tables.impl_defaultness.set_some(def_id.index, ast_item.defaultness); let impl_item = self.tcx.associated_item(def_id); - self.tables.assoc_container.set(def_id.index, impl_item.container); + self.tables.assoc_container.set_some(def_id.index, impl_item.container); match impl_item.kind { ty::AssocKind::Fn => { let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; - self.tables.asyncness.set(def_id.index, sig.header.asyncness); + self.tables.asyncness.set_some(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); // Can be inside `impl const Trait`, so using sig.header.constness is not reliable let constness = if self.tcx.is_const_fn_raw(def_id) { @@ -1382,18 +1380,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { hir::Constness::NotConst }; - self.tables.constness.set(def_id.index, constness); + self.tables.constness.set_some(def_id.index, constness); } ty::AssocKind::Const | ty::AssocKind::Type => {} } if let Some(trait_item_def_id) = impl_item.trait_item_def_id { - self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into()); + self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into()); } if impl_item.kind == ty::AssocKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); - if tcx.is_intrinsic(def_id) { - self.tables.is_intrinsic.set_nullable(def_id.index, true); - } + self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } } @@ -1522,14 +1518,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { match item.kind { hir::ItemKind::Fn(ref sig, .., body) => { - self.tables.asyncness.set(def_id.index, sig.header.asyncness); + self.tables.asyncness.set_some(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); - self.tables.constness.set(def_id.index, sig.header.constness); + self.tables.constness.set_some(def_id.index, sig.header.constness); } hir::ItemKind::Macro(ref macro_def, _) => { - if macro_def.macro_rules { - self.tables.is_macro_rules.set_nullable(def_id.index, true); - } + self.tables.is_macro_rules.set(def_id.index, macro_def.macro_rules); record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { @@ -1537,20 +1531,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(ref opaque) => { self.encode_explicit_item_bounds(def_id); - if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) { - self.tables.is_type_alias_impl_trait.set_nullable(def_id.index, true); - } + self.tables + .is_type_alias_impl_trait + .set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)); } hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { - self.tables.impl_defaultness.set(def_id.index, *defaultness); - self.tables.constness.set(def_id.index, *constness); + self.tables.impl_defaultness.set_some(def_id.index, *defaultness); + self.tables.constness.set_some(def_id.index, *constness); let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder); if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { - self.tables.impl_parent.set(def_id.index, parent.into()); + self.tables.impl_parent.set_some(def_id.index, parent.into()); } } @@ -1564,7 +1558,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let polarity = self.tcx.impl_polarity(def_id); - self.tables.impl_polarity.set(def_id.index, polarity); + self.tables.impl_polarity.set_some(def_id.index, polarity); } hir::ItemKind::Trait(..) => { let trait_def = self.tcx.trait_def(def_id); @@ -1601,9 +1595,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let hir::ItemKind::Fn(..) = item.kind { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); - if tcx.is_intrinsic(def_id) { - self.tables.is_intrinsic.set_nullable(def_id.index, true); - } + self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } if let hir::ItemKind::Impl { .. } = item.kind { if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { @@ -1650,7 +1642,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ty::Closure(_, substs) => { let constness = self.tcx.constness(def_id.to_def_id()); - self.tables.constness.set(def_id.to_def_id().index, constness); + self.tables.constness.set_some(def_id.to_def_id().index, constness); record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder(substs.as_closure().sig())); } @@ -1678,12 +1670,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.hygiene_ctxt.encode( &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table), |(this, syntax_contexts, _, _), index, ctxt_data| { - syntax_contexts.set(index, this.lazy(ctxt_data)); + syntax_contexts.set_some(index, this.lazy(ctxt_data)); }, |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| { if let Some(index) = index.as_local() { - expn_data_table.set(index.as_raw(), this.lazy(expn_data)); - expn_hash_table.set(index.as_raw(), this.lazy(hash)); + expn_data_table.set_some(index.as_raw(), this.lazy(expn_data)); + expn_hash_table.set_some(index.as_raw(), this.lazy(hash)); } }, ); @@ -1708,10 +1700,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); for (i, span) in spans.into_iter().enumerate() { let span = self.lazy(span); - self.tables.proc_macro_quoted_spans.set(i, span); + self.tables.proc_macro_quoted_spans.set_some(i, span); } - self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod); + self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod); record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local()); let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index); @@ -1753,8 +1745,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_key.disambiguated_data.data = DefPathData::MacroNs(name); let def_id = id.to_def_id(); - self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind)); - self.tables.proc_macro.set(def_id.index, macro_kind); + self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind)); + self.tables.proc_macro.set_some(def_id.index, macro_kind); self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); @@ -1979,22 +1971,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { match nitem.kind { hir::ForeignItemKind::Fn(_, ref names, _) => { - self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync); + self.tables.asyncness.set_some(def_id.index, hir::IsAsync::NotAsync); record_array!(self.tables.fn_arg_names[def_id] <- *names); let constness = if self.tcx.is_const_fn_raw(def_id) { hir::Constness::Const } else { hir::Constness::NotConst }; - self.tables.constness.set(def_id.index, constness); + self.tables.constness.set_some(def_id.index, constness); record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {} } if let hir::ForeignItemKind::Fn(..) = nitem.kind { - if tcx.is_intrinsic(def_id) { - self.tables.is_intrinsic.set_nullable(def_id.index, true); - } + self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id)); } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 37af9e64e9a3..da82ae253e6f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -316,7 +316,7 @@ pub(crate) struct IncoherentImpls { /// Define `LazyTables` and `TableBuilders` at the same time. macro_rules! define_tables { ( - - nullable: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+ + - defaulted: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+ - optional: $($name2:ident: Table<$IDX2:ty, $T2:ty>,)+ ) => { #[derive(MetadataEncodable, MetadataDecodable)] @@ -343,7 +343,7 @@ macro_rules! define_tables { } define_tables! { -- nullable: +- defaulted: is_intrinsic: Table, is_macro_rules: Table, is_type_alias_impl_trait: Table, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 70dbf6476e2f..78cf9149f7d6 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -10,11 +10,39 @@ use rustc_span::hygiene::MacroKind; use std::marker::PhantomData; use std::num::NonZeroUsize; +pub(super) trait IsDefault: Default { + fn is_default(&self) -> bool; +} + +impl IsDefault for Option { + fn is_default(&self) -> bool { + self.is_none() + } +} + +impl IsDefault for AttrFlags { + fn is_default(&self) -> bool { + self.is_empty() + } +} + +impl IsDefault for bool { + fn is_default(&self) -> bool { + !self + } +} + +impl IsDefault for u32 { + fn is_default(&self) -> bool { + *self == 0 + } +} + /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. /// Used mainly for Lazy positions and lengths. /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, /// but this has no impact on safety. -pub(super) trait FixedSizeEncoding: Default { +pub(super) trait FixedSizeEncoding: IsDefault { /// This should be `[u8; BYTE_LEN]`; /// Cannot use an associated `const BYTE_LEN: usize` instead due to const eval limitations. type ByteArray; @@ -23,6 +51,8 @@ pub(super) trait FixedSizeEncoding: Default { fn write_to_bytes(self, b: &mut Self::ByteArray); } +/// This implementation is not used generically, but for reading/writing +/// concrete `u32` fields in `Lazy*` structures, which may be zero. impl FixedSizeEncoding for u32 { type ByteArray = [u8; 4]; @@ -58,7 +88,7 @@ macro_rules! fixed_size_enum { fn write_to_bytes(self, b: &mut [u8;1]) { use $ty::*; b[0] = match self { - None => 0, + None => unreachable!(), $(Some($($pat)*) => 1 + ${index()},)* } } @@ -160,15 +190,16 @@ impl FixedSizeEncoding for Option { #[inline] fn from_bytes(b: &[u8; 16]) -> Self { + // NOTE: There's a collision between `None` and `Some(0)`. Some(DefPathHash(Fingerprint::from_le_bytes(*b))) } #[inline] fn write_to_bytes(self, b: &mut [u8; 16]) { - let Some(DefPathHash(fingerprint)) = self else { - panic!("Trying to encode absent DefPathHash.") - }; - *b = fingerprint.to_le_bytes(); + match self { + None => unreachable!(), + Some(DefPathHash(fingerprint)) => *b = fingerprint.to_le_bytes(), + } } } @@ -179,17 +210,17 @@ impl FixedSizeEncoding for Option { #[inline] fn from_bytes(b: &[u8; 8]) -> Self { let krate = u32::from_le_bytes(b[0..4].try_into().unwrap()); - let index = u32::from_le_bytes(b[4..8].try_into().unwrap()); if krate == 0 { return None; } + let index = u32::from_le_bytes(b[4..8].try_into().unwrap()); Some(RawDefId { krate: krate - 1, index }) } #[inline] fn write_to_bytes(self, b: &mut [u8; 8]) { match self { - None => *b = [0; 8], + None => unreachable!(), Some(RawDefId { krate, index }) => { // CrateNum is less than `CrateNum::MAX_AS_U32`. debug_assert!(krate < u32::MAX); @@ -210,6 +241,7 @@ impl FixedSizeEncoding for AttrFlags { #[inline] fn write_to_bytes(self, b: &mut [u8; 1]) { + debug_assert!(!self.is_default()); b[0] = self.bits(); } } @@ -224,6 +256,7 @@ impl FixedSizeEncoding for bool { #[inline] fn write_to_bytes(self, b: &mut [u8; 1]) { + debug_assert!(!self.is_default()); b[0] = self as u8 } } @@ -242,9 +275,14 @@ impl FixedSizeEncoding for Option> { #[inline] fn write_to_bytes(self, b: &mut [u8; 4]) { - let position = self.map_or(0, |lazy| lazy.position.get()); - let position: u32 = position.try_into().unwrap(); - position.write_to_bytes(b) + match self { + None => unreachable!(), + Some(lazy) => { + let position = lazy.position.get(); + let position: u32 = position.try_into().unwrap(); + position.write_to_bytes(b) + } + } } } @@ -253,7 +291,7 @@ impl FixedSizeEncoding for Option> { #[inline] fn from_bytes(b: &[u8; 8]) -> Self { - let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() }; + let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() }; let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?; let len = u32::from_bytes(meta_bytes) as usize; Some(LazyArray::from_position_and_num_elems(position, len)) @@ -261,15 +299,20 @@ impl FixedSizeEncoding for Option> { #[inline] fn write_to_bytes(self, b: &mut [u8; 8]) { - let ([ref mut position_bytes, ref mut meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() }; + match self { + None => unreachable!(), + Some(lazy) => { + let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() }; - let position = self.map_or(0, |lazy| lazy.position.get()); - let position: u32 = position.try_into().unwrap(); - position.write_to_bytes(position_bytes); + let position = lazy.position.get(); + let position: u32 = position.try_into().unwrap(); + position.write_to_bytes(position_bytes); - let len = self.map_or(0, |lazy| lazy.num_elems); - let len: u32 = len.try_into().unwrap(); - len.write_to_bytes(meta_bytes); + let len = lazy.num_elems; + let len: u32 = len.try_into().unwrap(); + len.write_to_bytes(meta_bytes); + } + } } } @@ -289,20 +332,27 @@ impl TableBuilder> where Option: FixedSizeEncoding, { - pub(crate) fn set(&mut self, i: I, value: T) { - self.set_nullable(i, Some(value)) + pub(crate) fn set_some(&mut self, i: I, value: T) { + self.set(i, Some(value)) } } impl> TableBuilder { - pub(crate) fn set_nullable(&mut self, i: I, value: T) { - // FIXME(eddyb) investigate more compact encodings for sparse tables. - // On the PR @michaelwoerister mentioned: - // > Space requirements could perhaps be optimized by using the HAMT `popcnt` - // > trick (i.e. divide things into buckets of 32 or 64 items and then - // > store bit-masks of which item in each bucket is actually serialized). - self.blocks.ensure_contains_elem(i, || [0; N]); - value.write_to_bytes(&mut self.blocks[i]); + /// Sets the table value if it is not default. + /// ATTENTION: For optimization default values are simply ignored by this function, because + /// right now metadata tables never need to reset non-default values to default. If such need + /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced + /// for doing that explicitly. + pub(crate) fn set(&mut self, i: I, value: T) { + if !value.is_default() { + // FIXME(eddyb) investigate more compact encodings for sparse tables. + // On the PR @michaelwoerister mentioned: + // > Space requirements could perhaps be optimized by using the HAMT `popcnt` + // > trick (i.e. divide things into buckets of 32 or 64 items and then + // > store bit-masks of which item in each bucket is actually serialized). + self.blocks.ensure_contains_elem(i, || [0; N]); + value.write_to_bytes(&mut self.blocks[i]); + } } pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable { @@ -331,10 +381,7 @@ where let start = self.position.get(); let bytes = &metadata.blob()[start..start + self.encoded_size]; let (bytes, []) = bytes.as_chunks::() else { panic!() }; - match bytes.get(i.index()) { - Some(bytes) => FixedSizeEncoding::from_bytes(bytes), - None => FixedSizeEncoding::from_bytes(&[0; N]), - } + bytes.get(i.index()).map_or_else(Default::default, FixedSizeEncoding::from_bytes) } /// Size of the table in entries, including possible gaps. From eb5f2d3980aa80fd91173401b167d55ec431a512 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 27 Jan 2023 23:28:33 +0400 Subject: [PATCH 113/137] rustc_metadata: Support encoding/decoding `LazyArray` without an `Option` --- compiler/rustc_metadata/src/rmeta/decoder.rs | 18 +++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- compiler/rustc_metadata/src/rmeta/mod.rs | 10 ++-- compiler/rustc_metadata/src/rmeta/table.rs | 62 +++++++++++++++----- 4 files changed, 66 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index bb2dd290c6d5..3125111b2bd0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -654,7 +654,7 @@ impl<'a, 'tcx, T> Decodable> for LazyValue { impl<'a, 'tcx, T> Decodable> for LazyArray { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { let len = decoder.read_usize(); - if len == 0 { LazyArray::empty() } else { decoder.read_lazy_array(len) } + if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) } } } @@ -864,7 +864,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, index) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .map(|index| ty::FieldDef { did: self.local_def_id(index), @@ -896,7 +896,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, item_id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .filter_map(|index| { let kind = self.def_kind(index); @@ -1045,7 +1045,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .fn_arg_names .get(self, id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode((self, sess)) .nth(0) .map_or(false, |ident| ident.name == kw::SelfLower) @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode((self, sess)) .map(move |child_index| self.local_def_id(child_index)) } @@ -1131,7 +1131,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .map(move |index| respan(self.get_span(index, sess), self.item_name(index))) } @@ -1144,7 +1144,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .map(move |field_index| self.get_visibility(field_index)) } @@ -1159,7 +1159,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inherent_impls .get(self, id) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .map(|index| self.local_def_id(index)), ) @@ -1174,7 +1174,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inherent_impls .get(self, ty_index) - .unwrap_or_else(LazyArray::empty) + .unwrap_or_else(LazyArray::default) .decode(self) .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index))) }) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0533aacbd2fa..ed63e9409651 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -76,13 +76,13 @@ pub(super) struct EncodeContext<'a, 'tcx> { symbol_table: FxHashMap, } -/// If the current crate is a proc-macro, returns early with `LazyArray::empty()`. +/// If the current crate is a proc-macro, returns early with `LazyArray::default()`. /// This is useful for skipping the encoding of things that aren't needed /// for proc-macro crates. macro_rules! empty_proc_macro { ($self:ident) => { if $self.is_proc_macro { - return LazyArray::empty(); + return LazyArray::default(); } }; } @@ -1961,7 +1961,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Linkage::Static => Some(LinkagePreference::RequireStatic), })); } - LazyArray::empty() + LazyArray::default() } fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index da82ae253e6f..d8c778b935ed 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -115,14 +115,16 @@ impl ParameterizedOverTcx for LazyArray { type Value<'tcx> = LazyArray>; } +impl Default for LazyArray { + fn default() -> LazyArray { + LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0) + } +} + impl LazyArray { fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray { LazyArray { position, num_elems, _marker: PhantomData } } - - fn empty() -> LazyArray { - LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0) - } } /// A list of lazily-decoded values, with the added capability of random access. diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 78cf9149f7d6..11916553db51 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -38,6 +38,12 @@ impl IsDefault for u32 { } } +impl IsDefault for LazyArray { + fn is_default(&self) -> bool { + self.num_elems == 0 + } +} + /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. /// Used mainly for Lazy positions and lengths. /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, @@ -286,32 +292,60 @@ impl FixedSizeEncoding for Option> { } } +impl LazyArray { + #[inline] + fn write_to_bytes_impl(self, b: &mut [u8; 8]) { + let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() }; + + let position = self.position.get(); + let position: u32 = position.try_into().unwrap(); + position.write_to_bytes(position_bytes); + + let len = self.num_elems; + let len: u32 = len.try_into().unwrap(); + len.write_to_bytes(meta_bytes); + } + + fn from_bytes_impl(position_bytes: &[u8; 4], meta_bytes: &[u8; 4]) -> Option> { + let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?; + let len = u32::from_bytes(meta_bytes) as usize; + Some(LazyArray::from_position_and_num_elems(position, len)) + } +} + +impl FixedSizeEncoding for LazyArray { + type ByteArray = [u8; 8]; + + #[inline] + fn from_bytes(b: &[u8; 8]) -> Self { + let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() }; + if *meta_bytes == [0; 4] { + return Default::default(); + } + LazyArray::from_bytes_impl(position_bytes, meta_bytes).unwrap() + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8; 8]) { + assert!(!self.is_default()); + self.write_to_bytes_impl(b) + } +} + impl FixedSizeEncoding for Option> { type ByteArray = [u8; 8]; #[inline] fn from_bytes(b: &[u8; 8]) -> Self { let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() }; - let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?; - let len = u32::from_bytes(meta_bytes) as usize; - Some(LazyArray::from_position_and_num_elems(position, len)) + LazyArray::from_bytes_impl(position_bytes, meta_bytes) } #[inline] fn write_to_bytes(self, b: &mut [u8; 8]) { match self { None => unreachable!(), - Some(lazy) => { - let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() }; - - let position = lazy.position.get(); - let position: u32 = position.try_into().unwrap(); - position.write_to_bytes(position_bytes); - - let len = lazy.num_elems; - let len: u32 = len.try_into().unwrap(); - len.write_to_bytes(meta_bytes); - } + Some(lazy) => lazy.write_to_bytes_impl(b), } } } From c60cc439858a028d8ecc2be1e7468c04cc36e8f2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Feb 2023 16:28:12 +0400 Subject: [PATCH 114/137] rustc_metadata: Encode/decode some `LazyArray`s without an `Option` Also add asserts to decoding `LazyArray`s with `Option` --- compiler/rustc_metadata/src/rmeta/decoder.rs | 23 +++++++--------- .../src/rmeta/decoder/cstore_impl.rs | 13 +++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 27 ++++++++++--------- compiler/rustc_metadata/src/rmeta/mod.rs | 8 +++--- compiler/rustc_ty_utils/src/assoc.rs | 9 ++++--- 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3125111b2bd0..06c8c32c4b30 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -864,7 +864,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, index) - .unwrap_or_else(LazyArray::default) + .expect("fields are not encoded for a variant") .decode(self) .map(|index| ty::FieldDef { did: self.local_def_id(index), @@ -896,7 +896,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, item_id) - .unwrap_or_else(LazyArray::default) + .expect("variants are not encoded for an enum") .decode(self) .filter_map(|index| { let kind = self.def_kind(index); @@ -1045,7 +1045,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .fn_arg_names .get(self, id) - .unwrap_or_else(LazyArray::default) + .expect("argument names not encoded for a function") .decode((self, sess)) .nth(0) .map_or(false, |ident| ident.name == kw::SelfLower) @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::default) + .expect("associated items not encoded for an item") .decode((self, sess)) .map(move |child_index| self.local_def_id(child_index)) } @@ -1068,13 +1068,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { let name = self.item_name(id); - let kind = match self.def_kind(id) { - DefKind::AssocConst => ty::AssocKind::Const, - DefKind::AssocFn => ty::AssocKind::Fn, - DefKind::AssocTy => ty::AssocKind::Type, + let (kind, has_self) = match self.def_kind(id) { + DefKind::AssocConst => (ty::AssocKind::Const, false), + DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)), + DefKind::AssocTy => (ty::AssocKind::Type, false), _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; - let has_self = self.get_fn_has_self_parameter(id, sess); let container = self.root.tables.assoc_container.get(self, id).unwrap(); ty::AssocItem { @@ -1131,7 +1130,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::default) + .expect("fields not encoded for a struct") .decode(self) .map(move |index| respan(self.get_span(index, sess), self.item_name(index))) } @@ -1144,7 +1143,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .children .get(self, id) - .unwrap_or_else(LazyArray::default) + .expect("fields not encoded for a struct") .decode(self) .map(move |field_index| self.get_visibility(field_index)) } @@ -1159,7 +1158,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inherent_impls .get(self, id) - .unwrap_or_else(LazyArray::default) .decode(self) .map(|index| self.local_def_id(index)), ) @@ -1174,7 +1172,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inherent_impls .get(self, ty_index) - .unwrap_or_else(LazyArray::default) .decode(self) .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index))) }) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9b1401f4a44d..07cc84ab9536 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -1,6 +1,7 @@ use crate::creader::{CStore, LoadedMacro}; use crate::foreign_modules; use crate::native_libs; +use crate::rmeta::table::IsDefault; use crate::rmeta::AttrFlags; use rustc_ast as ast; @@ -88,6 +89,14 @@ macro_rules! provide_one { } } }; + ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_defaulted_array }) => { + provide_one! { + $tcx, $def_id, $other, $cdata, $name => { + let lazy = $cdata.root.tables.$name.get($cdata, $def_id.index); + if lazy.is_default() { &[] } else { $tcx.arena.alloc_from_iter(lazy.decode(($cdata, $tcx))) } + } + } + }; ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => { provide_one! { $tcx, $def_id, $other, $cdata, $name => { @@ -187,10 +196,10 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } provide! { tcx, def_id, other, cdata, - explicit_item_bounds => { table } + explicit_item_bounds => { table_defaulted_array } explicit_predicates_of => { table } generics_of => { table } - inferred_outlives_of => { table } + inferred_outlives_of => { table_defaulted_array } super_predicates_of => { table } type_of => { table } variances_of => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ed63e9409651..07c37b296219 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -389,6 +389,16 @@ macro_rules! record_array { }}; } +macro_rules! record_defaulted_array { + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ + { + let value = $value; + let lazy = $self.lazy_array(value); + $self.$tables.$table.set($def_id.index, lazy); + } + }}; +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn emit_lazy_distance(&mut self, position: NonZeroUsize) { let pos = position.get(); @@ -1190,9 +1200,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.generics_of[def_id] <- g); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); let inferred_outlives = self.tcx.inferred_outlives_of(def_id); - if !inferred_outlives.is_empty() { - record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); - } + record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); } if should_encode_type(tcx, local_id, def_kind) { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); @@ -1213,15 +1221,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } } + let inherent_impls = tcx.with_stable_hashing_context(|hcx| { tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true) }); - - for (def_id, implementations) in inherent_impls { - if implementations.is_empty() { - continue; - } - record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| { + for (def_id, impls) in inherent_impls { + record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| { assert!(def_id.is_local()); def_id.index })); @@ -1330,9 +1335,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_explicit_item_bounds(&mut self, def_id: DefId) { debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); let bounds = self.tcx.explicit_item_bounds(def_id); - if !bounds.is_empty() { - record_array!(self.tables.explicit_item_bounds[def_id] <- bounds); - } + record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds); } fn encode_info_for_trait_item(&mut self, def_id: DefId) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index d8c778b935ed..f0b9bf045372 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -350,6 +350,9 @@ define_tables! { is_macro_rules: Table, is_type_alias_impl_trait: Table, attr_flags: Table, + explicit_item_bounds: Table, Span)>>, + inferred_outlives_of: Table, Span)>>, + inherent_impls: Table>, - optional: attributes: Table>, @@ -362,12 +365,8 @@ define_tables! { lookup_const_stability: Table>, lookup_default_body_stability: Table>, lookup_deprecation_entry: Table>, - // As an optimization, a missing entry indicates an empty `&[]`. - explicit_item_bounds: Table, Span)>>, explicit_predicates_of: Table>>, generics_of: Table>, - // As an optimization, a missing entry indicates an empty `&[]`. - inferred_outlives_of: Table, Span)>>, super_predicates_of: Table>>, type_of: Table>>, variances_of: Table>, @@ -395,7 +394,6 @@ define_tables! { generator_kind: Table>, trait_def: Table>, trait_item_def_id: Table, - inherent_impls: Table>, expn_that_defined: Table>, unused_generic_params: Table>, params_in_repr: Table>>, diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 424b52309d3a..a6e0f13f6983 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -22,14 +22,17 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), ), - hir::ItemKind::TraitAlias(..) => &[], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } } fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { - let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssocItems::new(items) + if tcx.is_trait_alias(def_id) { + ty::AssocItems::new(Vec::new()) + } else { + let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); + ty::AssocItems::new(items) + } } fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap { From 7a752788367d06e4bc20351e5235bea8c11667b4 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 3 Feb 2023 12:23:37 +0300 Subject: [PATCH 115/137] Recover from missing expression in for loop --- .../rustc_error_messages/locales/en-US/parse.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 12 ++++++++++++ compiler/rustc_parse/src/parser/expr.rs | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 244eb41eb39e..2ef3dba557ea 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -128,6 +128,9 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop .use_in_not_of = try using `in` here instead .add_in = try adding `in` here +parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop + .suggestion = try adding an expression to the `for` loop + parse_missing_comma_after_match_arm = expected `,` following `match` arm .suggestion = missing a comma here to end this `match` arm diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fd4333dbbecc..fc7c839f1c46 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -433,6 +433,18 @@ pub(crate) enum MissingInInForLoopSub { AddIn(#[primary_span] Span), } +#[derive(Diagnostic)] +#[diag(parse_missing_expression_in_for_loop)] +pub(crate) struct MissingExpressionInForLoop { + #[primary_span] + #[suggestion( + code = "/* expression */ ", + applicability = "has-placeholders", + style = "verbose" + )] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_missing_comma_after_match_arm)] pub(crate) struct MissingCommaAfterMatchArm { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 473a5bb8cb8c..c37808f8c3d1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2471,6 +2471,21 @@ impl<'a> Parser<'a> { let pat = self.recover_parens_around_for_head(pat, begin_paren); + // Recover from missing expression in `for` loop + if matches!(expr.kind, ExprKind::Block(..)) + && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace)) + && self.may_recover() + { + self.sess + .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() }); + let err_expr = self.mk_expr(expr.span, ExprKind::Err); + let block = self.mk_block(vec![], BlockCheckMode::Default, self.prev_token.span); + return Ok(self.mk_expr( + lo.to(self.prev_token.span), + ExprKind::ForLoop(pat, err_expr, block, opt_label), + )); + } + let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); From 17b6bd6b70fd49c034b32b5b9b2869d139ed4d46 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 3 Feb 2023 12:25:01 +0300 Subject: [PATCH 116/137] Add ui test for missing expression in for loop --- tests/ui/parser/missing-expression-in-for-loop.rs | 5 +++++ .../ui/parser/missing-expression-in-for-loop.stderr | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/parser/missing-expression-in-for-loop.rs create mode 100644 tests/ui/parser/missing-expression-in-for-loop.stderr diff --git a/tests/ui/parser/missing-expression-in-for-loop.rs b/tests/ui/parser/missing-expression-in-for-loop.rs new file mode 100644 index 000000000000..518a89a0e6fc --- /dev/null +++ b/tests/ui/parser/missing-expression-in-for-loop.rs @@ -0,0 +1,5 @@ +fn main() { + for i in { + //~^ ERROR missing expression to iterate on in `for` loop + } +} diff --git a/tests/ui/parser/missing-expression-in-for-loop.stderr b/tests/ui/parser/missing-expression-in-for-loop.stderr new file mode 100644 index 000000000000..74a7c4224fae --- /dev/null +++ b/tests/ui/parser/missing-expression-in-for-loop.stderr @@ -0,0 +1,13 @@ +error: missing expression to iterate on in `for` loop + --> $DIR/missing-expression-in-for-loop.rs:2:14 + | +LL | for i in { + | ^ + | +help: try adding an expression to the `for` loop + | +LL | for i in /* expression */ { + | ++++++++++++++++ + +error: aborting due to previous error + From f4e2b954a1749bb215eb0f1365e7d1f95162d3ba Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Feb 2023 18:53:47 +0400 Subject: [PATCH 117/137] rustc_metadata: Encode/decode `DefPathHash`es without an `Option` --- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_metadata/src/rmeta/table.rs | 17 ++++++++++------- compiler/rustc_span/src/def_id.rs | 6 ++++++ 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 06c8c32c4b30..e2b07fad6e78 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1319,7 +1319,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) -> DefPathHash { *def_path_hashes .entry(index) - .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index).unwrap()) + .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index)) } #[inline] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 07c37b296219..85e9ae9a9830 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -478,13 +478,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_key = self.lazy(table.def_key(def_index)); let def_path_hash = table.def_path_hash(def_index); self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set_some(def_index, def_path_hash); + self.tables.def_path_hashes.set(def_index, def_path_hash); } } else { for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() { let def_key = self.lazy(def_key); self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set_some(def_index, *def_path_hash); + self.tables.def_path_hashes.set(def_index, *def_path_hash); } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index f0b9bf045372..a74aa381d9eb 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -350,6 +350,7 @@ define_tables! { is_macro_rules: Table, is_type_alias_impl_trait: Table, attr_flags: Table, + def_path_hashes: Table, explicit_item_bounds: Table, Span)>>, inferred_outlives_of: Table, Span)>>, inherent_impls: Table>, @@ -403,7 +404,6 @@ define_tables! { // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - def_path_hashes: Table, proc_macro_quoted_spans: Table>, generator_diagnostic_data: Table>>, variant_data: Table>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 11916553db51..99bec570600a 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -44,6 +44,12 @@ impl IsDefault for LazyArray { } } +impl IsDefault for DefPathHash { + fn is_default(&self) -> bool { + self.0 == Fingerprint::ZERO + } +} + /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. /// Used mainly for Lazy positions and lengths. /// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, @@ -191,21 +197,18 @@ fixed_size_enum! { } // We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost. -impl FixedSizeEncoding for Option { +impl FixedSizeEncoding for DefPathHash { type ByteArray = [u8; 16]; #[inline] fn from_bytes(b: &[u8; 16]) -> Self { - // NOTE: There's a collision between `None` and `Some(0)`. - Some(DefPathHash(Fingerprint::from_le_bytes(*b))) + DefPathHash(Fingerprint::from_le_bytes(*b)) } #[inline] fn write_to_bytes(self, b: &mut [u8; 16]) { - match self { - None => unreachable!(), - Some(DefPathHash(fingerprint)) => *b = fingerprint.to_le_bytes(), - } + debug_assert!(!self.is_default()); + *b = self.0.to_le_bytes(); } } diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 7c5e1427d1ed..cdda052f5290 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -119,6 +119,12 @@ impl DefPathHash { } } +impl Default for DefPathHash { + fn default() -> Self { + DefPathHash(Fingerprint::ZERO) + } +} + impl Borrow for DefPathHash { #[inline] fn borrow(&self) -> &Fingerprint { From dae00152e7d95c98a085d56583415551acb9151c Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Sun, 5 Feb 2023 16:26:51 +0100 Subject: [PATCH 118/137] Sort Generator `print-type-sizes` according to their yield points Especially when trying to diagnose runaway future sizes, it might be more intuitive to sort the variants according to the control flow (aka their yield points) rather than the size of the variants. --- compiler/rustc_session/src/code_stats.rs | 6 +++++- compiler/rustc_ty_utils/src/layout.rs | 11 ++++++++++- tests/ui/async-await/future-sizes/large-arg.stdout | 10 +++++----- tests/ui/print_type_sizes/async.stdout | 4 ++-- tests/ui/print_type_sizes/generator.stdout | 4 ++-- .../print_type_sizes/generator_discr_placement.stdout | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index 87dfccdef2f1..55178250472e 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -84,7 +84,11 @@ impl CodeStats { // Sort variants so the largest ones are shown first. A stable sort is // used here so that source code order is preserved for all variants // that have the same size. - variants.sort_by(|info1, info2| info2.size.cmp(&info1.size)); + // Except for Generators, whose variants are already sorted according to + // their yield points in `variant_info_for_generator`. + if kind != DataTypeKind::Generator { + variants.sort_by(|info1, info2| info2.size.cmp(&info1.size)); + } let info = TypeSizeInfo { kind, type_description: type_desc.to_string(), diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 93c9c675c9a6..2aeb255c1641 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -970,7 +970,7 @@ fn variant_info_for_generator<'tcx>( }) .collect(); - let variant_infos: Vec<_> = generator + let mut variant_infos: Vec<_> = generator .variant_fields .iter_enumerated() .map(|(variant_idx, variant_def)| { @@ -1033,6 +1033,15 @@ fn variant_info_for_generator<'tcx>( } }) .collect(); + + // The first three variants are hardcoded to be `UNRESUMED`, `RETURNED` and `POISONED`. + // We will move the `RETURNED` and `POISONED` elements to the end so we + // are left with a sorting order according to the generators yield points: + // First `Unresumed`, then the `SuspendN` followed by `Returned` and `Panicked` (POISONED). + let end_states = variant_infos.drain(1..=2); + let end_states: Vec<_> = end_states.collect(); + variant_infos.extend(end_states); + ( variant_infos, match tag_encoding { diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index c206d7931707..91db4b1531f5 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -1,17 +1,17 @@ print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 3075 bytes print-type-size local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Suspend0`: 3074 bytes print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size local `.__awaitee`: 2050 bytes -print-type-size variant `Unresumed`: 1024 bytes -print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes @@ -24,11 +24,11 @@ print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 3075 bytes print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 1024 bytes +print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Suspend0`: 2049 bytes print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size local `.__awaitee`: 1025 bytes -print-type-size variant `Unresumed`: 1024 bytes -print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1024 bytes diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index 4588c0ebd81b..8fe936efc898 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -1,11 +1,11 @@ print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 8192 bytes +print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Suspend0`: 16385 bytes print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size local `.arg`: 8192 bytes print-type-size local `.__awaitee`: 1 bytes -print-type-size variant `Unresumed`: 8192 bytes -print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 8192 bytes diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/generator.stdout index 13d850a66902..7c58d6ce5ffa 100644 --- a/tests/ui/print_type_sizes/generator.stdout +++ b/tests/ui/print_type_sizes/generator.stdout @@ -2,9 +2,9 @@ print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, a print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 8192 bytes print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Suspend0`: 8192 bytes +print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Returned`: 8192 bytes print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 8192 bytes print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size variant `Suspend0`: 8192 bytes -print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout index b294b2d139c3..f2a11c7a33ba 100644 --- a/tests/ui/print_type_sizes/generator_discr_placement.stdout +++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout @@ -1,11 +1,11 @@ print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 7 bytes print-type-size padding: 3 bytes print-type-size local `.w`: 4 bytes, alignment: 4 bytes print-type-size variant `Suspend1`: 7 bytes print-type-size padding: 3 bytes print-type-size local `.z`: 4 bytes, alignment: 4 bytes -print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes From f5c45ad2847910d8df0c2adaf07a3b27bfca86f2 Mon Sep 17 00:00:00 2001 From: Kiran Shila Date: Sun, 5 Feb 2023 10:13:30 -0800 Subject: [PATCH 119/137] Fix typo in HashMap::with_capacity --- library/std/src/collections/hash/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index df490358827e..742c4cc7c553 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -238,7 +238,7 @@ impl HashMap { /// /// The hash map will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash set will not allocate. + /// `capacity`. If `capacity` is 0, the hash map will not allocate. /// /// # Examples /// From bac7628eae905b0c806788914c9b7ee9409983de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Feb 2023 09:00:56 +1100 Subject: [PATCH 120/137] Put a `ShallowResolver` within `OpportunisticVarResolver`. So one doesn't have to be constructed every time. --- compiler/rustc_infer/src/infer/resolve.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 65b90aa3d79d..49cd9a9c3d0f 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -16,26 +16,28 @@ use std::ops::ControlFlow; /// useful for printing messages etc but also required at various /// points for correctness. pub struct OpportunisticVarResolver<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, + // The shallow resolver is used to resolve inference variables at every + // level of the type. + shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>, } impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> { #[inline] pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - OpportunisticVarResolver { infcx } + OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } } } } impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { - self.infcx.tcx + TypeFolder::tcx(&self.shallow_resolver) } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if !t.has_non_region_infer() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else { - let t = self.infcx.shallow_resolve(t); + let t = self.shallow_resolver.fold_ty(t); t.super_fold_with(self) } } @@ -44,7 +46,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { if !ct.has_non_region_infer() { ct // micro-optimize -- if there is nothing in this const that this fold affects... } else { - let ct = self.infcx.shallow_resolve(ct); + let ct = self.shallow_resolver.fold_const(ct); ct.super_fold_with(self) } } From f08a3371b01f6d6b01bf351f28bf0fbba2bd1b87 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Feb 2023 10:15:24 +1100 Subject: [PATCH 121/137] Improve early bailout test in `resolve_vars_if_possible`. `!t.has_non_region_infer()` is the test used in `OpportunisticVarResolver`, and catches a few cases that `!t.needs_infer()` misses. --- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f39170bb2916..14af720fca1f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1389,8 +1389,8 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - if !value.needs_infer() { - return value; // Avoid duplicated subst-folding. + if !value.has_non_region_infer() { + return value; } let mut r = resolve::OpportunisticVarResolver::new(self); value.fold_with(&mut r) From c2cf3f7b24b4667f72b12da547b57c02741f0615 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Feb 2023 10:31:11 +1100 Subject: [PATCH 122/137] Inline `OpportunisticVarResolver::fold_ty`. --- compiler/rustc_infer/src/infer/resolve.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 49cd9a9c3d0f..a39a40cf9abe 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -33,6 +33,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { TypeFolder::tcx(&self.shallow_resolver) } + #[inline] fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if !t.has_non_region_infer() { t // micro-optimize -- if there is nothing in this type that this fold affects... From fb8e6819aa59c215a2974454d0cbeca34830321a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Feb 2023 12:36:44 +1100 Subject: [PATCH 123/137] Split and inline `ShallowResolver::fold_ty`. --- compiler/rustc_infer/src/infer/mod.rs | 83 +++++++++++++++------------ 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 14af720fca1f..8e0bcff8d0a8 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::visit::TypeVisitable; pub use rustc_middle::ty::IntVarValue; -use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -1870,43 +1870,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { /// If `ty` is a type variable of some kind, resolve it one level /// (but do not resolve types found in the result). If `typ` is /// not a type variable, just return it unmodified. + #[inline] fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Infer(ty::TyVar(v)) => { - // Not entirely obvious: if `typ` is a type variable, - // it can be resolved to an int/float variable, which - // can then be recursively resolved, hence the - // recursion. Note though that we prevent type - // variables from unifying to other type variables - // directly (though they may be embedded - // structurally), and we prevent cycles in any case, - // so this recursion should always be of very limited - // depth. - // - // Note: if these two lines are combined into one we get - // dynamic borrow errors on `self.inner`. - let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - known.map_or(ty, |t| self.fold_ty(t)) - } - - ty::Infer(ty::IntVar(v)) => self - .infcx - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map_or(ty, |v| v.to_type(self.infcx.tcx)), - - ty::Infer(ty::FloatVar(v)) => self - .infcx - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map_or(ty, |v| v.to_type(self.infcx.tcx)), - - _ => ty, - } + if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty } } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -1925,6 +1891,49 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { } } +impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { + // This is separate from `fold_ty` to keep that method small and inlinable. + #[inline(never)] + fn fold_infer_ty(&mut self, v: InferTy) -> Option> { + match v { + ty::TyVar(v) => { + // Not entirely obvious: if `typ` is a type variable, + // it can be resolved to an int/float variable, which + // can then be recursively resolved, hence the + // recursion. Note though that we prevent type + // variables from unifying to other type variables + // directly (though they may be embedded + // structurally), and we prevent cycles in any case, + // so this recursion should always be of very limited + // depth. + // + // Note: if these two lines are combined into one we get + // dynamic borrow errors on `self.inner`. + let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); + known.map(|t| self.fold_ty(t)) + } + + ty::IntVar(v) => self + .infcx + .inner + .borrow_mut() + .int_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + + ty::FloatVar(v) => self + .infcx + .inner + .borrow_mut() + .float_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None, + } + } +} + impl<'tcx> TypeTrace<'tcx> { pub fn span(&self) -> Span { self.cause.span From 4aec1345aa5deabba4b63a71f5fb9bd2a3fde01b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 3 Feb 2023 11:36:32 +1100 Subject: [PATCH 124/137] Split and inline `TypeFreshener::fold_ty`. --- compiler/rustc_infer/src/infer/freshen.rs | 129 ++++++++++------------ 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 83d71edc2abd..2355234637c4 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -140,79 +140,21 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } } + #[inline] fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if !t.needs_infer() && !t.has_erasable_regions() { - return t; - } + t + } else { + match *t.kind() { + ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t), - let tcx = self.infcx.tcx; + // This code is hot enough that a non-debug assertion here makes a noticeable + // difference on benchmarks like `wg-grammar`. + #[cfg(debug_assertions)] + ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), - match *t.kind() { - ty::Infer(ty::TyVar(v)) => { - let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy) + _ => t.super_fold_with(self), } - - ty::Infer(ty::IntVar(v)) => self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(tcx)), - ty::IntVar(v), - ty::FreshIntTy, - ), - - ty::Infer(ty::FloatVar(v)) => self.freshen_ty( - self.infcx - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(tcx)), - ty::FloatVar(v), - ty::FreshFloatTy, - ), - - ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => { - if ct >= self.ty_freshen_count { - bug!( - "Encountered a freshend type with id {} \ - but our counter is only at {}", - ct, - self.ty_freshen_count - ); - } - t - } - - ty::Generator(..) - | ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Adt(..) - | ty::Str - | ty::Error(_) - | ty::Array(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Dynamic(..) - | ty::Never - | ty::Tuple(..) - | ty::Alias(..) - | ty::Foreign(..) - | ty::Param(..) - | ty::Closure(..) - | ty::GeneratorWitnessMIR(..) - | ty::GeneratorWitness(..) => t.super_fold_with(self), - - ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), } } @@ -253,3 +195,54 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } } } + +impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { + // This is separate from `fold_ty` to keep that method small and inlinable. + #[inline(never)] + fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option> { + match v { + ty::TyVar(v) => { + let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); + Some(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)) + } + + ty::IntVar(v) => Some( + self.freshen_ty( + self.infcx + .inner + .borrow_mut() + .int_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + ty::IntVar(v), + ty::FreshIntTy, + ), + ), + + ty::FloatVar(v) => Some( + self.freshen_ty( + self.infcx + .inner + .borrow_mut() + .float_unification_table() + .probe_value(v) + .map(|v| v.to_type(self.infcx.tcx)), + ty::FloatVar(v), + ty::FreshFloatTy, + ), + ), + + ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => { + if ct >= self.ty_freshen_count { + bug!( + "Encountered a freshend type with id {} \ + but our counter is only at {}", + ct, + self.ty_freshen_count + ); + } + None + } + } + } +} From 4a7a9b4e74fce7d39e53aeae3b85cdfc7bb588a6 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Sun, 5 Feb 2023 19:38:08 -0800 Subject: [PATCH 125/137] Clarify wording on f64::round() and f32::round() "Round half-way cases" is a little confusing (it's a 'garden path sentence' as it's not immediately clear whether round is an adjective or verb). Make this sentence longer and clearer. --- library/std/src/f32.rs | 4 ++-- library/std/src/f64.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 4e3007624631..6b1f0cba82df 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -69,8 +69,8 @@ impl f32 { unsafe { intrinsics::ceilf32(self) } } - /// Returns the nearest integer to `self`. Round half-way cases away from - /// `0.0`. + /// Returns the nearest integer to `self`. If a value is half-way between two + /// integers, round away from `0.0`. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index ec67fdad4f72..16359766b510 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -69,8 +69,8 @@ impl f64 { unsafe { intrinsics::ceilf64(self) } } - /// Returns the nearest integer to `self`. Round half-way cases away from - /// `0.0`. + /// Returns the nearest integer to `self`. If a value is half-way between two + /// integers, round away from `0.0`. /// /// # Examples /// From 6b05b80690fe6548b49da46f85b9ec7b1ea95e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 5 Feb 2023 14:22:41 +0800 Subject: [PATCH 126/137] Suggest return type for async function without return type --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 16 +++++++++ .../src/fn_ctxt/suggestions.rs | 30 +++++++++++++++- .../issue-90027-async-fn-return-suggestion.rs | 21 +++++++++++ ...ue-90027-async-fn-return-suggestion.stderr | 36 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs create mode 100644 tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 237142acca66..e84b3de124c5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -921,6 +921,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::ImplItemKind::Fn(ref sig, ..), .. }) => Some((&sig.decl, ident, false)), + Node::Expr(&hir::Expr { + hir_id, + kind: hir::ExprKind::Closure(..), + .. + }) if let Some(Node::Expr(&hir::Expr { + hir_id, + kind: hir::ExprKind::Call(..), + .. + })) = self.tcx.hir().find_parent(hir_id) && + let Some(Node::Item(&hir::Item { + ident, + kind: hir::ItemKind::Fn(ref sig, ..), + .. + })) = self.tcx.hir().find_parent(hir_id) => { + Some((&sig.decl, ident, ident.name != sym::main)) + }, _ => None, } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 11d47053ade7..84341e680331 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -704,10 +704,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } hir::FnRetTy::Return(ty) => { + let span = ty.span; + + if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind + && let hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(op_ty), + .. + }) = self.tcx.hir().get(item_id.hir_id()) + && let hir::OpaqueTy { + bounds: [bound], .. + } = op_ty + && let hir::GenericBound::LangItemTrait( + hir::LangItem::Future, _, _, generic_args) = bound + && let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args + && let hir::TypeBinding { kind, .. } = ty_binding + && let hir::TypeBindingKind::Equality { term } = kind + && let hir::Term::Ty(term_ty) = term { + // Check if async function's return type was omitted. + // Don't emit suggestions if the found type is `impl Future<...>`. + debug!("suggest_missing_return_type: found = {:?}", found); + if found.is_suggestable(self.tcx, false) { + if term_ty.span.is_empty() { + err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() }); + return true; + } else { + err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected }); + } + } + } + // Only point to return type if the expected type is the return type, as if they // are not, the expectation must have been caused by something else. debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind); - let span = ty.span; let ty = self.astconv().ast_ty_to_ty(ty); debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs new file mode 100644 index 000000000000..8ccb15ca48a4 --- /dev/null +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs @@ -0,0 +1,21 @@ +// edition:2018 + +async fn hello() { //~ HELP try adding a return type + 0 + //~^ ERROR [E0308] +} + +async fn world() -> () { + 0 + //~^ ERROR [E0308] +} + +async fn suggest_await_in_async_fn_return() { + hello() + //~^ ERROR mismatched types [E0308] + //~| HELP consider `await`ing on the `Future` + //~| HELP consider using a semicolon here + //~| SUGGESTION .await +} + +fn main() {} diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr new file mode 100644 index 000000000000..6a1a9f45bc62 --- /dev/null +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5 + | +LL | async fn hello() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5 + | +LL | async fn world() -> () { + | -- expected `()` because of return type +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5 + | +LL | hello() + | ^^^^^^^ expected `()`, found opaque type + | + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | hello().await + | ++++++ +help: consider using a semicolon here + | +LL | hello(); + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From c58202eb9b2c196e922fba56b89283b63b6afe69 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 6 Feb 2023 11:22:44 +0200 Subject: [PATCH 127/137] end entry paragprah with a period (.) --- library/core/src/num/uint_macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1c97c4686283..dcc0835ecd6d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -18,7 +18,7 @@ macro_rules! uint_impl { pub const MIN: Self = 0; /// The largest value that can be represented by this integer type - #[doc = concat!("(2", $BITS, " − 1", $bound_condition, ")")] + #[doc = concat!("(2", $BITS, " − 1", $bound_condition, ").")] /// /// # Examples /// From 201ae7387245caa4591d4c8db4c35c170c64faf0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Dec 2022 12:31:17 +0100 Subject: [PATCH 128/137] make PointerKind directly reflect pointer types The code that consumes PointerKind (`adjust_for_rust_scalar` in rustc_ty_utils) ended up using PointerKind variants to talk about Rust reference types (& and &mut) anyway, making the old code structure quite confusing: one always had to keep in mind which PointerKind corresponds to which type. So this changes PointerKind to directly reflect the type. This does not change behavior. --- compiler/rustc_abi/src/lib.rs | 21 ++++-------- compiler/rustc_middle/src/ty/layout.rs | 39 +++++++---------------- compiler/rustc_ty_utils/src/abi.rs | 33 ++++++++++--------- tests/codegen/function-arguments-noopt.rs | 6 ++++ 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 5af6206c0bb8..9126c516d381 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1439,21 +1439,12 @@ impl fmt::Debug for LayoutS { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PointerKind { - /// Most general case, we know no restrictions to tell LLVM. - SharedMutable, - - /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`. - Frozen, - - /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`. - UniqueBorrowed, - - /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`. - UniqueBorrowedPinned, - - /// `Box`, which is `noalias` (even on return types, unlike the above) but neither `readonly` - /// nor `dereferenceable`. - UniqueOwned, + /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`. + SharedRef { frozen: bool }, + /// Mutable reference. `unpin` indicates the absence of any pinned data. + MutableRef { unpin: bool }, + /// Box. + Box, } /// Note that this information is advisory only, and backends are free to ignore it. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cdcd6281f209..1244922c6d4a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -833,32 +833,17 @@ where }) } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { - let kind = if tcx.sess.opts.optimize == OptLevel::No { - // Use conservative pointer kind if not optimizing. This saves us the - // Freeze/Unpin queries, and can save time in the codegen backend (noalias - // attributes in LLVM have compile-time cost even in unoptimized builds). - PointerKind::SharedMutable - } else { - match mt { - hir::Mutability::Not => { - if ty.is_freeze(tcx, cx.param_env()) { - PointerKind::Frozen - } else { - PointerKind::SharedMutable - } - } - hir::Mutability::Mut => { - // References to self-referential structures should not be considered - // noalias, as another pointer to the structure can be obtained, that - // is not based-on the original reference. We consider all !Unpin - // types to be potentially self-referential here. - if ty.is_unpin(tcx, cx.param_env()) { - PointerKind::UniqueBorrowed - } else { - PointerKind::UniqueBorrowedPinned - } - } - } + // Use conservative pointer kind if not optimizing. This saves us the + // Freeze/Unpin queries, and can save time in the codegen backend (noalias + // attributes in LLVM have compile-time cost even in unoptimized builds). + let optimize = tcx.sess.opts.optimize != OptLevel::No; + let kind = match mt { + hir::Mutability::Not => PointerKind::SharedRef { + frozen: optimize && ty.is_freeze(tcx, cx.param_env()), + }, + hir::Mutability::Mut => PointerKind::MutableRef { + unpin: optimize && ty.is_unpin(tcx, cx.param_env()), + }, }; tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { @@ -929,7 +914,7 @@ where if let Some(ref mut pointee) = result { if let ty::Adt(def, _) = this.ty.kind() { if def.is_box() && offset.bytes() == 0 { - pointee.safe = Some(PointerKind::UniqueOwned); + pointee.safe = Some(PointerKind::Box); } } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 1c74aeca5ab1..884087987ce0 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -254,15 +254,15 @@ fn adjust_for_rust_scalar<'tcx>( if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); - // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable - // for the entire duration of the function as they can be deallocated - // at any time. Same for shared mutable references. If LLVM had a - // way to say "dereferenceable on entry" we could use it here. + // `Box` are not necessarily dereferenceable for the entire duration of the function as + // they can be deallocated at any time. Same for non-frozen shared references (see + // ). If LLVM had a way to say + // "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::UniqueBorrowed - | PointerKind::UniqueBorrowedPinned - | PointerKind::Frozen => pointee.size, - PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO, + PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO, + PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => { + pointee.size + } }; // The aliasing rules for `Box` are still not decided, but currently we emit @@ -278,15 +278,14 @@ fn adjust_for_rust_scalar<'tcx>( // `&mut` pointer parameters never alias other parameters, // or mutable global data // - // `&T` where `T` contains no `UnsafeCell` is immutable, - // and can be marked as both `readonly` and `noalias`, as - // LLVM's definition of `noalias` is based solely on memory - // dependencies rather than pointer equality + // `&T` where `T` contains no `UnsafeCell` is immutable, and can be marked as both + // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory + // dependencies rather than pointer equality. However this only applies to arguments, + // not return values. let no_alias = match kind { - PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false, - PointerKind::UniqueBorrowed => noalias_mut_ref, - PointerKind::UniqueOwned => noalias_for_box, - PointerKind::Frozen => true, + PointerKind::SharedRef { frozen } => frozen, + PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, + PointerKind::Box => noalias_for_box, }; // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics // (see ). @@ -294,7 +293,7 @@ fn adjust_for_rust_scalar<'tcx>( attrs.set(ArgAttribute::NoAlias); } - if kind == PointerKind::Frozen && !is_return { + if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return { attrs.set(ArgAttribute::ReadOnly); } } diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs index ff76405a4ea3..0c62e0d35e36 100644 --- a/tests/codegen/function-arguments-noopt.rs +++ b/tests/codegen/function-arguments-noopt.rs @@ -29,6 +29,12 @@ pub fn borrow(x: &i32) -> &i32 { x } +// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x) +#[no_mangle] +pub fn borrow_mut(x: &mut i32) -> &mut i32 { + x +} + // CHECK-LABEL: @borrow_call #[no_mangle] pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 { From ea541bc2ee00c955e3f7eb3ddd5c3ab80146ab71 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Dec 2022 12:46:08 +0100 Subject: [PATCH 129/137] make &mut !Unpin not dereferenceable See https://github.com/rust-lang/unsafe-code-guidelines/issues/381 for discussion. --- compiler/rustc_ty_utils/src/abi.rs | 15 +++++--- .../src/borrow_tracker/stacked_borrows/mod.rs | 10 ++--- .../deallocate_against_protector2.rs | 16 -------- .../deallocate_against_protector2.stderr | 38 ------------------- .../pass/stacked-borrows/stacked-borrows.rs | 20 ++++++++++ tests/codegen/function-arguments.rs | 16 +++++++- 6 files changed, 48 insertions(+), 67 deletions(-) delete mode 100644 src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.rs delete mode 100644 src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 884087987ce0..4ee3202292af 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -256,13 +256,16 @@ fn adjust_for_rust_scalar<'tcx>( // `Box` are not necessarily dereferenceable for the entire duration of the function as // they can be deallocated at any time. Same for non-frozen shared references (see - // ). If LLVM had a way to say - // "dereferenceable on entry" we could use it here. + // ), and for mutable references to + // potentially self-referential types (see + // ). If LLVM had a way + // to say "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO, - PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => { - pointee.size - } + PointerKind::Box + | PointerKind::SharedRef { frozen: false } + | PointerKind::MutableRef { unpin: false } => Size::ZERO, + PointerKind::SharedRef { frozen: true } + | PointerKind::MutableRef { unpin: true } => pointee.size, }; // The aliasing rules for `Box` are still not decided, but currently we emit diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index ec555ba2895c..3b3a41c2f037 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -81,21 +81,18 @@ impl NewPermission { protector: None, } } else if pointee.is_unpin(*cx.tcx, cx.param_env()) { - // A regular full mutable reference. + // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), protector, } } else { + // `!Unpin` dereferences do not get `noalias` nor `dereferenceable`. NewPermission::Uniform { perm: Permission::SharedReadWrite, - // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we - // should do fake accesses here. But then we run into - // , so for now - // we don't do that. access: None, - protector, + protector: None, } } } @@ -109,6 +106,7 @@ impl NewPermission { } } ty::Ref(_, _pointee, Mutability::Not) => { + // Shared references. If frozen, these get `noalias` and `dereferenceable`; otherwise neither. NewPermission::FreezeSensitive { freeze_perm: Permission::SharedReadOnly, freeze_access: Some(AccessKind::Read), diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.rs b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.rs deleted file mode 100644 index fd67dccd14df..000000000000 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@error-pattern: /deallocating while item \[SharedReadWrite for .*\] is strongly protected/ -use std::marker::PhantomPinned; - -pub struct NotUnpin(i32, PhantomPinned); - -fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) { - // `f` may mutate, but it may not deallocate! - f(x) -} - -fn main() { - inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| { - let raw = x as *mut _; - drop(unsafe { Box::from_raw(raw) }); - }); -} diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr deleted file mode 100644 index 47cfa0de7258..000000000000 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: Undefined Behavior: deallocating while item [SharedReadWrite for ] is strongly protected by call ID - --> RUSTLIB/alloc/src/alloc.rs:LL:CC - | -LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [SharedReadWrite for ] is strongly protected by call ID - | - = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental - = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information - = note: BACKTRACE: - = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC - = note: inside `::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC - = note: inside `alloc::alloc::box_free::` at RUSTLIB/alloc/src/alloc.rs:LL:CC - = note: inside `std::ptr::drop_in_place::> - shim(Some(std::boxed::Box))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC - = note: inside `std::mem::drop::>` at RUSTLIB/core/src/mem/mod.rs:LL:CC -note: inside closure - --> $DIR/deallocate_against_protector2.rs:LL:CC - | -LL | drop(unsafe { Box::from_raw(raw) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: inside `<[closure@$DIR/deallocate_against_protector2.rs:LL:CC] as std::ops::FnOnce<(&mut NotUnpin,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC -note: inside `inner` - --> $DIR/deallocate_against_protector2.rs:LL:CC - | -LL | f(x) - | ^^^^ -note: inside `main` - --> $DIR/deallocate_against_protector2.rs:LL:CC - | -LL | / inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| { -LL | | let raw = x as *mut _; -LL | | drop(unsafe { Box::from_raw(raw) }); -LL | | }); - | |______^ - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to previous error - diff --git a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs index ef6eb346c17b..8e78efa73c75 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs @@ -19,6 +19,7 @@ fn main() { array_casts(); mut_below_shr(); wide_raw_ptr_in_tuple(); + not_unpin_not_protected(); } // Make sure that reading from an `&mut` does, like reborrowing to `&`, @@ -219,3 +220,22 @@ fn wide_raw_ptr_in_tuple() { // Make sure the fn ptr part of the vtable is still fine. r.type_id(); } + +fn not_unpin_not_protected() { + // `&mut !Unpin`, at least for now, does not get `noalias` nor `dereferenceable`, so we also + // don't add protectors. (We could, but until we have a better idea for where we want to go with + // the self-referntial-generator situation, it does not seem worth the potential trouble.) + use std::marker::PhantomPinned; + + pub struct NotUnpin(i32, PhantomPinned); + + fn inner(x: &mut NotUnpin, f: fn(&mut NotUnpin)) { + // `f` may mutate, but it may not deallocate! + f(x) + } + + inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| { + let raw = x as *mut _; + drop(unsafe { Box::from_raw(raw) }); + }); +} diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index 1f979d7b90a7..0f4639086b88 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -85,6 +85,12 @@ pub fn option_nonzero_int(x: Option) -> Option { pub fn readonly_borrow(_: &i32) { } +// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret() +#[no_mangle] +pub fn readonly_borrow_ret() -> &'static i32 { + loop {} +} + // CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1) // static borrow may be captured #[no_mangle] @@ -115,9 +121,17 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { pub fn mutable_borrow(_: &mut i32) { } +// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret() #[no_mangle] -// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1) +pub fn mutable_borrow_ret() -> &'static mut i32 { + loop {} +} + +#[no_mangle] +// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1) // This one is *not* `noalias` because it might be self-referential. +// It is also not `dereferenceable` due to +// . pub fn mutable_notunpin_borrow(_: &mut NotUnpin) { } From 1ef16874b5ef79e193526cd23eebd30d45826360 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Jan 2023 14:09:01 +0100 Subject: [PATCH 130/137] also do not add noalias on not-Unpin Box --- compiler/rustc_abi/src/lib.rs | 4 +- compiler/rustc_middle/src/ty/layout.rs | 192 +++++++++--------- compiler/rustc_ty_utils/src/abi.rs | 9 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 33 ++- .../future-self-referential.rs | 54 ++++- tests/codegen/function-arguments.rs | 10 +- 6 files changed, 183 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 9126c516d381..0306cb5ce6ab 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1443,8 +1443,8 @@ pub enum PointerKind { SharedRef { frozen: bool }, /// Mutable reference. `unpin` indicates the absence of any pinned data. MutableRef { unpin: bool }, - /// Box. - Box, + /// Box. `unpin` indicates the absence of any pinned data. + Box { unpin: bool }, } /// Note that this information is advisory only, and backends are free to ignore it. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1244922c6d4a..4c2855821384 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -818,110 +818,114 @@ where let tcx = cx.tcx(); let param_env = cx.param_env(); - let pointee_info = - match *this.ty.kind() { - ty::RawPtr(mt) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo { - size: layout.size, - align: layout.align.abi, - safe: None, - }) - } - ty::FnPtr(fn_sig) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| { - PointeeInfo { size: layout.size, align: layout.align.abi, safe: None } - }) - } - ty::Ref(_, ty, mt) if offset.bytes() == 0 => { - // Use conservative pointer kind if not optimizing. This saves us the - // Freeze/Unpin queries, and can save time in the codegen backend (noalias - // attributes in LLVM have compile-time cost even in unoptimized builds). - let optimize = tcx.sess.opts.optimize != OptLevel::No; - let kind = match mt { - hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, cx.param_env()), - }, - hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, cx.param_env()), - }, - }; + let pointee_info = match *this.ty.kind() { + ty::RawPtr(mt) if offset.bytes() == 0 => { + tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: None, + }) + } + ty::FnPtr(fn_sig) if offset.bytes() == 0 => { + tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: None, + }) + } + ty::Ref(_, ty, mt) if offset.bytes() == 0 => { + // Use conservative pointer kind if not optimizing. This saves us the + // Freeze/Unpin queries, and can save time in the codegen backend (noalias + // attributes in LLVM have compile-time cost even in unoptimized builds). + let optimize = tcx.sess.opts.optimize != OptLevel::No; + let kind = match mt { + hir::Mutability::Not => PointerKind::SharedRef { + frozen: optimize && ty.is_freeze(tcx, cx.param_env()), + }, + hir::Mutability::Mut => PointerKind::MutableRef { + unpin: optimize && ty.is_unpin(tcx, cx.param_env()), + }, + }; - tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { - size: layout.size, - align: layout.align.abi, - safe: Some(kind), - }) - } + tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { + size: layout.size, + align: layout.align.abi, + safe: Some(kind), + }) + } - _ => { - let mut data_variant = match this.variants { - // Within the discriminant field, only the niche itself is - // always initialized, so we only check for a pointer at its - // offset. - // - // If the niche is a pointer, it's either valid (according - // to its type), or null (which the niche field's scalar - // validity range encodes). This allows using - // `dereferenceable_or_null` for e.g., `Option<&T>`, and - // this will continue to work as long as we don't start - // using more niches than just null (e.g., the first page of - // the address space, or unaligned pointers). - Variants::Multiple { - tag_encoding: TagEncoding::Niche { untagged_variant, .. }, - tag_field, - .. - } if this.fields.offset(tag_field) == offset => { - Some(this.for_variant(cx, untagged_variant)) - } - _ => Some(this), - }; - - if let Some(variant) = data_variant { - // We're not interested in any unions. - if let FieldsShape::Union(_) = variant.fields { - data_variant = None; - } + _ => { + let mut data_variant = match this.variants { + // Within the discriminant field, only the niche itself is + // always initialized, so we only check for a pointer at its + // offset. + // + // If the niche is a pointer, it's either valid (according + // to its type), or null (which the niche field's scalar + // validity range encodes). This allows using + // `dereferenceable_or_null` for e.g., `Option<&T>`, and + // this will continue to work as long as we don't start + // using more niches than just null (e.g., the first page of + // the address space, or unaligned pointers). + Variants::Multiple { + tag_encoding: TagEncoding::Niche { untagged_variant, .. }, + tag_field, + .. + } if this.fields.offset(tag_field) == offset => { + Some(this.for_variant(cx, untagged_variant)) } + _ => Some(this), + }; - let mut result = None; + if let Some(variant) = data_variant { + // We're not interested in any unions. + if let FieldsShape::Union(_) = variant.fields { + data_variant = None; + } + } - if let Some(variant) = data_variant { - // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - // (requires passing in the expected address space from the caller) - let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx); - for i in 0..variant.fields.count() { - let field_start = variant.fields.offset(i); - if field_start <= offset { - let field = variant.field(cx, i); - result = field.to_result().ok().and_then(|field| { - if ptr_end <= field_start + field.size { - // We found the right field, look inside it. - let field_info = - field.pointee_info_at(cx, offset - field_start); - field_info - } else { - None - } - }); - if result.is_some() { - break; + let mut result = None; + + if let Some(variant) = data_variant { + // FIXME(erikdesjardins): handle non-default addrspace ptr sizes + // (requires passing in the expected address space from the caller) + let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx); + for i in 0..variant.fields.count() { + let field_start = variant.fields.offset(i); + if field_start <= offset { + let field = variant.field(cx, i); + result = field.to_result().ok().and_then(|field| { + if ptr_end <= field_start + field.size { + // We found the right field, look inside it. + let field_info = + field.pointee_info_at(cx, offset - field_start); + field_info + } else { + None } + }); + if result.is_some() { + break; } } } - - // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. - if let Some(ref mut pointee) = result { - if let ty::Adt(def, _) = this.ty.kind() { - if def.is_box() && offset.bytes() == 0 { - pointee.safe = Some(PointerKind::Box); - } - } - } - - result } - }; + + // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. + if let Some(ref mut pointee) = result { + if let ty::Adt(def, _) = this.ty.kind() { + if def.is_box() && offset.bytes() == 0 { + let optimize = tcx.sess.opts.optimize != OptLevel::No; + pointee.safe = Some(PointerKind::Box { + unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), + }); + } + } + } + + result + } + }; debug!( "pointee_info_at (offset={:?}, type kind: {:?}) => {:?}", diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 4ee3202292af..ad5527f5a778 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -261,7 +261,7 @@ fn adjust_for_rust_scalar<'tcx>( // ). If LLVM had a way // to say "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::Box + PointerKind::Box { .. } | PointerKind::SharedRef { frozen: false } | PointerKind::MutableRef { unpin: false } => Size::ZERO, PointerKind::SharedRef { frozen: true } @@ -278,17 +278,16 @@ fn adjust_for_rust_scalar<'tcx>( // versions at all anymore. We still support turning it off using -Zmutable-noalias. let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias; - // `&mut` pointer parameters never alias other parameters, - // or mutable global data - // // `&T` where `T` contains no `UnsafeCell` is immutable, and can be marked as both // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory // dependencies rather than pointer equality. However this only applies to arguments, // not return values. + // + // `&mut T` and `Box` where `T: Unpin` are unique and hence `noalias`. let no_alias = match kind { PointerKind::SharedRef { frozen } => frozen, PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, - PointerKind::Box => noalias_for_box, + PointerKind::Box { unpin } => unpin && noalias_for_box, }; // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics // (see ). diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 3b3a41c2f037..106e93751d21 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -135,6 +135,32 @@ impl NewPermission { } } + fn from_box_ty<'tcx>( + ty: Ty<'tcx>, + kind: RetagKind, + cx: &crate::MiriInterpCx<'_, 'tcx>, + ) -> Self { + // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). + let pointee = ty.builtin_deref(true).unwrap().ty; + if pointee.is_unpin(*cx.tcx, cx.param_env()) { + // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only + // a weak protector). + NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector: (kind == RetagKind::FnEntry) + .then_some(ProtectorKind::WeakProtector), + } + } else { + // `!Unpin` boxes do not get `noalias` nor `dereferenceable`. + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + access: None, + protector: None, + } + } + } + fn protector(&self) -> Option { match self { NewPermission::Uniform { protector, .. } => *protector, @@ -914,12 +940,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { // Boxes get a weak protectors, since they may be deallocated. - let new_perm = NewPermission::Uniform { - perm: Permission::Unique, - access: Some(AccessKind::Write), - protector: (self.kind == RetagKind::FnEntry) - .then_some(ProtectorKind::WeakProtector), - }; + let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx); self.retag_ptr_inplace(place, new_perm, self.retag_cause) } diff --git a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs index 96fc0be344db..6994def16a1d 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/future-self-referential.rs @@ -26,6 +26,19 @@ impl Future for Delay { } } +fn mk_waker() -> Waker { + use std::sync::Arc; + + struct MyWaker; + impl Wake for MyWaker { + fn wake(self: Arc) { + unimplemented!() + } + } + + Waker::from(Arc::new(MyWaker)) +} + async fn do_stuff() { (&mut Delay::new(1)).await; } @@ -73,16 +86,7 @@ impl Future for DoStuff { } fn run_fut(fut: impl Future) -> T { - use std::sync::Arc; - - struct MyWaker; - impl Wake for MyWaker { - fn wake(self: Arc) { - unimplemented!() - } - } - - let waker = Waker::from(Arc::new(MyWaker)); + let waker = mk_waker(); let mut context = Context::from_waker(&waker); let mut pinned = pin!(fut); @@ -94,7 +98,37 @@ fn run_fut(fut: impl Future) -> T { } } +fn self_referential_box() { + let waker = mk_waker(); + let cx = &mut Context::from_waker(&waker); + + async fn my_fut() -> i32 { + let val = 10; + let val_ref = &val; + + let _ = Delay::new(1).await; + + *val_ref + } + + fn box_poll( + mut f: Pin>, + cx: &mut Context<'_>, + ) -> (Pin>, Poll) { + let p = f.as_mut().poll(cx); + (f, p) + } + + let my_fut = Box::pin(my_fut()); + let (my_fut, p1) = box_poll(my_fut, cx); + assert!(p1.is_pending()); + let (my_fut, p2) = box_poll(my_fut, cx); + assert!(p2.is_ready()); + drop(my_fut); +} + fn main() { run_fut(do_stuff()); run_fut(DoStuff::new()); + self_referential_box(); } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index 0f4639086b88..96dfde18683e 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -181,6 +181,12 @@ pub fn _box(x: Box) -> Box { x } +// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @notunpin_box({{i32\*|ptr}} noundef nonnull align 4 %x) +#[no_mangle] +pub fn notunpin_box(x: Box) -> Box { + x +} + // CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %0)?}}) #[no_mangle] pub fn struct_return() -> S { @@ -247,12 +253,12 @@ pub fn trait_raw(_: *const dyn Drop) { // CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) #[no_mangle] -pub fn trait_box(_: Box) { +pub fn trait_box(_: Box) { } // CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1) #[no_mangle] -pub fn trait_option(x: Option>) -> Option> { +pub fn trait_option(x: Option>) -> Option> { x } From 4f5f9f0a13afb4bcaaa67d4a7a944e2c182d5c02 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 6 Feb 2023 16:26:31 +0300 Subject: [PATCH 131/137] remove unused imports --- Cargo.lock | 17 ----------------- compiler/rustc_ast_lowering/Cargo.toml | 2 -- compiler/rustc_ast_pretty/Cargo.toml | 1 - compiler/rustc_codegen_llvm/Cargo.toml | 1 - compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_const_eval/Cargo.toml | 1 - compiler/rustc_hir_analysis/Cargo.toml | 3 --- compiler/rustc_infer/Cargo.toml | 1 - compiler/rustc_interface/Cargo.toml | 1 - compiler/rustc_mir_build/Cargo.toml | 1 - compiler/rustc_mir_dataflow/Cargo.toml | 1 - compiler/rustc_privacy/Cargo.toml | 1 - compiler/rustc_query_impl/Cargo.toml | 1 - compiler/rustc_trait_selection/Cargo.toml | 1 - compiler/rustc_traits/Cargo.toml | 1 - 15 files changed, 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 705210e44b24..b2948fb38959 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3689,7 +3689,6 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ - "rustc_arena", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -3698,7 +3697,6 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -3731,7 +3729,6 @@ name = "rustc_ast_pretty" version = "0.0.0" dependencies = [ "rustc_ast", - "rustc_parse_format", "rustc_span", ] @@ -3838,7 +3835,6 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_query_system", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_symbol_mangling", @@ -3864,7 +3860,6 @@ dependencies = [ "rustc_arena", "rustc_ast", "rustc_attr", - "rustc_const_eval", "rustc_data_structures", "rustc_errors", "rustc_fs_util", @@ -3905,7 +3900,6 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_mir_dataflow", - "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -4100,15 +4094,12 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_graphviz", "rustc_hir", - "rustc_hir_pretty", "rustc_index", "rustc_infer", "rustc_lint", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4195,7 +4186,6 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_serialize", - "rustc_session", "rustc_span", "rustc_target", "smallvec", @@ -4238,7 +4228,6 @@ dependencies = [ "rustc_privacy", "rustc_query_impl", "rustc_resolve", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_symbol_mangling", @@ -4404,7 +4393,6 @@ dependencies = [ "rustc_apfloat", "rustc_arena", "rustc_ast", - "rustc_attr", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4436,7 +4424,6 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_serialize", - "rustc_session", "rustc_span", "rustc_target", "smallvec", @@ -4567,7 +4554,6 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "rustc_trait_selection", "tracing", ] @@ -4588,7 +4574,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "rustc_target", "thin-vec", "tracing", ] @@ -4789,7 +4774,6 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", - "rustc_lint_defs", "rustc_macros", "rustc_middle", "rustc_parse_format", @@ -4811,7 +4795,6 @@ dependencies = [ "chalk-ir", "chalk-solve", "rustc_ast", - "rustc_attr", "rustc_data_structures", "rustc_hir", "rustc_index", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6a59b9e6151c..6e76c349a4a0 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" doctest = false [dependencies] -rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -16,7 +15,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } rustc_macros = { path = "../rustc_macros" } -rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index b4900dc39a8a..d1513c114fef 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -7,5 +7,4 @@ edition = "2021" [dependencies] rustc_ast = { path = "../rustc_ast" } -rustc_parse_format = { path = "../rustc_parse_format" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 9c1bcd431ec4..773c0ebbe59d 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -30,7 +30,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } -rustc_serialize = { path = "../rustc_serialize" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 0d2d2ec68a23..c55991e00d3a 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -41,7 +41,6 @@ rustc_metadata = { path = "../rustc_metadata" } rustc_query_system = { path = "../rustc_query_system" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } -rustc_const_eval = { path = "../rustc_const_eval" } [dependencies.object] version = "0.30.1" diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 51489e293606..98ac36c1ced7 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -19,7 +19,6 @@ rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } -rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 0761d8cdbd8f..c939c8303bf2 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -15,9 +15,7 @@ rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } @@ -27,6 +25,5 @@ rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_lint = { path = "../rustc_lint" } -rustc_serialize = { path = "../rustc_serialize" } rustc_type_ir = { path = "../rustc_type_ir" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index aced787d6711..02ac83a5e8b2 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -15,7 +15,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 1199ff287c43..955ab3c4680a 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -20,7 +20,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_serialize = { path = "../rustc_serialize" } rustc_middle = { path = "../rustc_middle" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 4ad3343d3031..f24b165d7c23 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -11,7 +11,6 @@ tracing = "0.1" either = "1" rustc_middle = { path = "../rustc_middle" } rustc_apfloat = { path = "../rustc_apfloat" } -rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 324644b67928..68c61a18d72f 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -19,6 +19,5 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } -rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 832fdc9f0166..744cb77dd00c 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -13,6 +13,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } tracing = "0.1" diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 46e77626479c..21732d260354 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -20,7 +20,6 @@ rustc-rayon-core = { version = "0.4.0", optional = true } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } thin-vec = "0.2.9" tracing = "0.1" diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 90d879976c26..3f863038efb3 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -16,7 +16,6 @@ rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } -rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index a432498abcca..eff6fb26dd4c 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] tracing = "0.1" -rustc_attr = { path = "../rustc_attr" } rustc_middle = { path = "../rustc_middle" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } From 3b494a41d9e87c636a9d5b094a15b8b6db2c6cc2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Feb 2023 16:04:10 +0100 Subject: [PATCH 132/137] Turn MarkdownWithToc into a struct with named fields --- src/librustdoc/html/markdown.rs | 18 +++++++++--------- src/librustdoc/markdown.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 00e3f859bfcb..fb7c34118a49 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -102,14 +102,14 @@ pub struct Markdown<'a> { /// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `

`. pub heading_offset: HeadingOffset, } -/// A tuple struct like `Markdown` that renders the markdown with a table of contents. -pub(crate) struct MarkdownWithToc<'a>( - pub(crate) &'a str, - pub(crate) &'a mut IdMap, - pub(crate) ErrorCodes, - pub(crate) Edition, - pub(crate) &'a Option, -); +/// A struct like `Markdown` that renders the markdown with a table of contents. +pub(crate) struct MarkdownWithToc<'a> { + pub(crate) content: &'a str, + pub(crate) ids: &'a mut IdMap, + pub(crate) error_codes: ErrorCodes, + pub(crate) edition: Edition, + pub(crate) playground: &'a Option, +} /// A tuple struct like `Markdown` that renders the markdown escaping HTML tags /// and includes no paragraph tags. pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap); @@ -1048,7 +1048,7 @@ impl Markdown<'_> { impl MarkdownWithToc<'_> { pub(crate) fn into_string(self) -> String { - let MarkdownWithToc(md, ids, codes, edition, playground) = self; + let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self; let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 5f4ad6d2aea3..4321d4aa343d 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -72,7 +72,14 @@ pub(crate) fn render>( let mut ids = IdMap::new(); let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); let text = if !options.markdown_no_toc { - MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string() + MarkdownWithToc { + content: text, + ids: &mut ids, + error_codes, + edition, + playground: &playground, + } + .into_string() } else { Markdown { content: text, From e1926b21102059dbedc67e9906a02049ef8ad839 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 6 Feb 2023 17:08:34 +0100 Subject: [PATCH 133/137] interpret: move discriminant reading and writing to separate file --- .../src/interpret/discriminant.rs | 238 ++++++++++++++++++ .../rustc_const_eval/src/interpret/mod.rs | 1 + .../rustc_const_eval/src/interpret/operand.rs | 153 +---------- .../rustc_const_eval/src/interpret/place.rs | 87 +------ 4 files changed, 245 insertions(+), 234 deletions(-) create mode 100644 compiler/rustc_const_eval/src/interpret/discriminant.rs diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs new file mode 100644 index 000000000000..557e721249d7 --- /dev/null +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -0,0 +1,238 @@ +//! Functions for reading and writing discriminants of multi-variant layouts (enums and generators). + +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; +use rustc_middle::{mir, ty}; +use rustc_target::abi::{self, TagEncoding}; +use rustc_target::abi::{VariantIdx, Variants}; + +use super::{ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Scalar}; + +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { + /// Writes the discriminant of the given variant. + #[instrument(skip(self), level = "trace")] + pub fn write_discriminant( + &mut self, + variant_index: VariantIdx, + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + // Layout computation excludes uninhabited variants from consideration + // therefore there's no way to represent those variants in the given layout. + // Essentially, uninhabited variants do not have a tag that corresponds to their + // discriminant, so we cannot do anything here. + // When evaluating we will always error before even getting here, but ConstProp 'executes' + // dead code, so we cannot ICE here. + if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() { + throw_ub!(UninhabitedEnumVariantWritten) + } + + match dest.layout.variants { + abi::Variants::Single { index } => { + assert_eq!(index, variant_index); + } + abi::Variants::Multiple { + tag_encoding: TagEncoding::Direct, + tag: tag_layout, + tag_field, + .. + } => { + // No need to validate that the discriminant here because the + // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. + + let discr_val = + dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val; + + // raw discriminants for enums are isize or bigger during + // their computation, but the in-memory tag is the smallest possible + // representation + let size = tag_layout.size(self); + let tag_val = size.truncate(discr_val); + + let tag_dest = self.place_field(dest, tag_field)?; + self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?; + } + abi::Variants::Multiple { + tag_encoding: + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, + tag: tag_layout, + tag_field, + .. + } => { + // No need to validate that the discriminant here because the + // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. + + if variant_index != untagged_variant { + let variants_start = niche_variants.start().as_u32(); + let variant_index_relative = variant_index + .as_u32() + .checked_sub(variants_start) + .expect("overflow computing relative variant idx"); + // We need to use machine arithmetic when taking into account `niche_start`: + // tag_val = variant_index_relative + niche_start_val + let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; + let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); + let variant_index_relative_val = + ImmTy::from_uint(variant_index_relative, tag_layout); + let tag_val = self.binary_op( + mir::BinOp::Add, + &variant_index_relative_val, + &niche_start_val, + )?; + // Write result. + let niche_dest = self.place_field(dest, tag_field)?; + self.write_immediate(*tag_val, &niche_dest)?; + } + } + } + + Ok(()) + } + + /// Read discriminant, return the runtime value as well as the variant index. + /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! + #[instrument(skip(self), level = "trace")] + pub fn read_discriminant( + &self, + op: &OpTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, (Scalar, VariantIdx)> { + trace!("read_discriminant_value {:#?}", op.layout); + // Get type and layout of the discriminant. + let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?; + trace!("discriminant type: {:?}", discr_layout.ty); + + // We use "discriminant" to refer to the value associated with a particular enum variant. + // This is not to be confused with its "variant index", which is just determining its position in the + // declared list of variants -- they can differ with explicitly assigned discriminants. + // We use "tag" to refer to how the discriminant is encoded in memory, which can be either + // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). + let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants { + Variants::Single { index } => { + let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) { + Some(discr) => { + // This type actually has discriminants. + assert_eq!(discr.ty, discr_layout.ty); + Scalar::from_uint(discr.val, discr_layout.size) + } + None => { + // On a type without actual discriminants, variant is 0. + assert_eq!(index.as_u32(), 0); + Scalar::from_uint(index.as_u32(), discr_layout.size) + } + }; + return Ok((discr, index)); + } + Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { + (tag, tag_encoding, tag_field) + } + }; + + // There are *three* layouts that come into play here: + // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for + // the `Scalar` we return. + // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type, + // and used to interpret the value we read from the tag field. + // For the return value, a cast to `discr_layout` is performed. + // - The field storing the tag has a layout, which is very similar to `tag_layout` but + // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks. + + // Get layout for tag. + let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?; + + // Read tag and sanity-check `tag_layout`. + let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?; + assert_eq!(tag_layout.size, tag_val.layout.size); + assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed()); + trace!("tag value: {}", tag_val); + + // Figure out which discriminant and variant this corresponds to. + Ok(match *tag_encoding { + TagEncoding::Direct => { + let scalar = tag_val.to_scalar(); + // Generate a specific error if `tag_val` is not an integer. + // (`tag_bits` itself is only used for error messages below.) + let tag_bits = scalar + .try_to_int() + .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? + .assert_bits(tag_layout.size); + // Cast bits from tag layout to discriminant layout. + // After the checks we did above, this cannot fail, as + // discriminants are int-like. + let discr_val = + self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap(); + let discr_bits = discr_val.assert_bits(discr_layout.size); + // Convert discriminant to variant index, and catch invalid discriminants. + let index = match *op.layout.ty.kind() { + ty::Adt(adt, _) => { + adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits) + } + ty::Generator(def_id, substs, _) => { + let substs = substs.as_generator(); + substs + .discriminants(def_id, *self.tcx) + .find(|(_, var)| var.val == discr_bits) + } + _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), + } + .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?; + // Return the cast value, and the index. + (discr_val, index.0) + } + TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { + let tag_val = tag_val.to_scalar(); + // Compute the variant this niche value/"tag" corresponds to. With niche layout, + // discriminant (encoded in niche/tag) and variant index are the same. + let variants_start = niche_variants.start().as_u32(); + let variants_end = niche_variants.end().as_u32(); + let variant = match tag_val.try_to_int() { + Err(dbg_val) => { + // So this is a pointer then, and casting to an int failed. + // Can only happen during CTFE. + // The niche must be just 0, and the ptr not null, then we know this is + // okay. Everything else, we conservatively reject. + let ptr_valid = niche_start == 0 + && variants_start == variants_end + && !self.scalar_may_be_null(tag_val)?; + if !ptr_valid { + throw_ub!(InvalidTag(dbg_val)) + } + untagged_variant + } + Ok(tag_bits) => { + let tag_bits = tag_bits.assert_bits(tag_layout.size); + // We need to use machine arithmetic to get the relative variant idx: + // variant_index_relative = tag_val - niche_start_val + let tag_val = ImmTy::from_uint(tag_bits, tag_layout); + let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); + let variant_index_relative_val = + self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; + let variant_index_relative = + variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size); + // Check if this is in the range that indicates an actual discriminant. + if variant_index_relative <= u128::from(variants_end - variants_start) { + let variant_index_relative = u32::try_from(variant_index_relative) + .expect("we checked that this fits into a u32"); + // Then computing the absolute variant idx should not overflow any more. + let variant_index = variants_start + .checked_add(variant_index_relative) + .expect("overflow computing absolute variant idx"); + let variants_len = op + .layout + .ty + .ty_adt_def() + .expect("tagged layout for non adt") + .variants() + .len(); + assert!(usize::try_from(variant_index).unwrap() < variants_len); + VariantIdx::from_u32(variant_index) + } else { + untagged_variant + } + } + }; + // Compute the size of the scalar we need to return. + // No need to cast, because the variant index directly serves as discriminant and is + // encoded in the tag. + (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant) + } + }) + } +} diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 2e356f67bf36..86de4e4e32c2 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -1,6 +1,7 @@ //! An interpreter for MIR used in CTFE and by miri mod cast; +mod discriminant; mod eval_context; mod intern; mod intrinsics; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index a1b3985dce4e..52613d5ca1f9 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,13 +4,12 @@ use either::{Either, Left, Right}; use rustc_hir::def::Namespace; -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, Ty, ValTree}; use rustc_middle::{mir, ty}; use rustc_span::Span; -use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding}; -use rustc_target::abi::{VariantIdx, Variants}; +use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size}; use super::{ alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId, @@ -657,154 +656,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; Ok(OpTy { op, layout, align: Some(layout.align.abi) }) } - - /// Read discriminant, return the runtime value as well as the variant index. - /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! - pub fn read_discriminant( - &self, - op: &OpTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (Scalar, VariantIdx)> { - trace!("read_discriminant_value {:#?}", op.layout); - // Get type and layout of the discriminant. - let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?; - trace!("discriminant type: {:?}", discr_layout.ty); - - // We use "discriminant" to refer to the value associated with a particular enum variant. - // This is not to be confused with its "variant index", which is just determining its position in the - // declared list of variants -- they can differ with explicitly assigned discriminants. - // We use "tag" to refer to how the discriminant is encoded in memory, which can be either - // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). - let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants { - Variants::Single { index } => { - let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) { - Some(discr) => { - // This type actually has discriminants. - assert_eq!(discr.ty, discr_layout.ty); - Scalar::from_uint(discr.val, discr_layout.size) - } - None => { - // On a type without actual discriminants, variant is 0. - assert_eq!(index.as_u32(), 0); - Scalar::from_uint(index.as_u32(), discr_layout.size) - } - }; - return Ok((discr, index)); - } - Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { - (tag, tag_encoding, tag_field) - } - }; - - // There are *three* layouts that come into play here: - // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for - // the `Scalar` we return. - // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type, - // and used to interpret the value we read from the tag field. - // For the return value, a cast to `discr_layout` is performed. - // - The field storing the tag has a layout, which is very similar to `tag_layout` but - // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks. - - // Get layout for tag. - let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?; - - // Read tag and sanity-check `tag_layout`. - let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?; - assert_eq!(tag_layout.size, tag_val.layout.size); - assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed()); - trace!("tag value: {}", tag_val); - - // Figure out which discriminant and variant this corresponds to. - Ok(match *tag_encoding { - TagEncoding::Direct => { - let scalar = tag_val.to_scalar(); - // Generate a specific error if `tag_val` is not an integer. - // (`tag_bits` itself is only used for error messages below.) - let tag_bits = scalar - .try_to_int() - .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? - .assert_bits(tag_layout.size); - // Cast bits from tag layout to discriminant layout. - // After the checks we did above, this cannot fail, as - // discriminants are int-like. - let discr_val = - self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap(); - let discr_bits = discr_val.assert_bits(discr_layout.size); - // Convert discriminant to variant index, and catch invalid discriminants. - let index = match *op.layout.ty.kind() { - ty::Adt(adt, _) => { - adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits) - } - ty::Generator(def_id, substs, _) => { - let substs = substs.as_generator(); - substs - .discriminants(def_id, *self.tcx) - .find(|(_, var)| var.val == discr_bits) - } - _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), - } - .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?; - // Return the cast value, and the index. - (discr_val, index.0) - } - TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { - let tag_val = tag_val.to_scalar(); - // Compute the variant this niche value/"tag" corresponds to. With niche layout, - // discriminant (encoded in niche/tag) and variant index are the same. - let variants_start = niche_variants.start().as_u32(); - let variants_end = niche_variants.end().as_u32(); - let variant = match tag_val.try_to_int() { - Err(dbg_val) => { - // So this is a pointer then, and casting to an int failed. - // Can only happen during CTFE. - // The niche must be just 0, and the ptr not null, then we know this is - // okay. Everything else, we conservatively reject. - let ptr_valid = niche_start == 0 - && variants_start == variants_end - && !self.scalar_may_be_null(tag_val)?; - if !ptr_valid { - throw_ub!(InvalidTag(dbg_val)) - } - untagged_variant - } - Ok(tag_bits) => { - let tag_bits = tag_bits.assert_bits(tag_layout.size); - // We need to use machine arithmetic to get the relative variant idx: - // variant_index_relative = tag_val - niche_start_val - let tag_val = ImmTy::from_uint(tag_bits, tag_layout); - let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); - let variant_index_relative_val = - self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?; - let variant_index_relative = - variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size); - // Check if this is in the range that indicates an actual discriminant. - if variant_index_relative <= u128::from(variants_end - variants_start) { - let variant_index_relative = u32::try_from(variant_index_relative) - .expect("we checked that this fits into a u32"); - // Then computing the absolute variant idx should not overflow any more. - let variant_index = variants_start - .checked_add(variant_index_relative) - .expect("overflow computing absolute variant idx"); - let variants_len = op - .layout - .ty - .ty_adt_def() - .expect("tagged layout for non adt") - .variants() - .len(); - assert!(usize::try_from(variant_index).unwrap() < variants_len); - VariantIdx::from_u32(variant_index) - } else { - untagged_variant - } - } - }; - // Compute the size of the scalar we need to return. - // No need to cast, because the variant index directly serves as discriminant and is - // encoded in the tag. - (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant) - } - }) - } } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 8d4d0420cda4..f82a41078d15 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -7,8 +7,8 @@ use either::{Either, Left, Right}; use rustc_ast::Mutability; use rustc_middle::mir; use rustc_middle::ty; -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; -use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding, VariantIdx}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, VariantIdx}; use super::{ alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, @@ -767,87 +767,8 @@ where MPlaceTy { mplace, layout, align: layout.align.abi } } - /// Writes the discriminant of the given variant. - #[instrument(skip(self), level = "debug")] - pub fn write_discriminant( - &mut self, - variant_index: VariantIdx, - dest: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx> { - // Layout computation excludes uninhabited variants from consideration - // therefore there's no way to represent those variants in the given layout. - // Essentially, uninhabited variants do not have a tag that corresponds to their - // discriminant, so we cannot do anything here. - // When evaluating we will always error before even getting here, but ConstProp 'executes' - // dead code, so we cannot ICE here. - if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() { - throw_ub!(UninhabitedEnumVariantWritten) - } - - match dest.layout.variants { - abi::Variants::Single { index } => { - assert_eq!(index, variant_index); - } - abi::Variants::Multiple { - tag_encoding: TagEncoding::Direct, - tag: tag_layout, - tag_field, - .. - } => { - // No need to validate that the discriminant here because the - // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. - - let discr_val = - dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val; - - // raw discriminants for enums are isize or bigger during - // their computation, but the in-memory tag is the smallest possible - // representation - let size = tag_layout.size(self); - let tag_val = size.truncate(discr_val); - - let tag_dest = self.place_field(dest, tag_field)?; - self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?; - } - abi::Variants::Multiple { - tag_encoding: - TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start }, - tag: tag_layout, - tag_field, - .. - } => { - // No need to validate that the discriminant here because the - // `TyAndLayout::for_variant()` call earlier already checks the variant is valid. - - if variant_index != untagged_variant { - let variants_start = niche_variants.start().as_u32(); - let variant_index_relative = variant_index - .as_u32() - .checked_sub(variants_start) - .expect("overflow computing relative variant idx"); - // We need to use machine arithmetic when taking into account `niche_start`: - // tag_val = variant_index_relative + niche_start_val - let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; - let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); - let variant_index_relative_val = - ImmTy::from_uint(variant_index_relative, tag_layout); - let tag_val = self.binary_op( - mir::BinOp::Add, - &variant_index_relative_val, - &niche_start_val, - )?; - // Write result. - let niche_dest = self.place_field(dest, tag_field)?; - self.write_immediate(*tag_val, &niche_dest)?; - } - } - } - - Ok(()) - } - - /// Writes the discriminant of the given variant. - #[instrument(skip(self), level = "debug")] + /// Writes the aggregate to the destination. + #[instrument(skip(self), level = "trace")] pub fn write_aggregate( &mut self, kind: &mir::AggregateKind<'tcx>, From 2ba0ec8adf669cb41f83a4cb65a7134e9c8beaa4 Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Mon, 6 Feb 2023 10:35:40 -0800 Subject: [PATCH 134/137] Add mailmap for commits made by xes@meta.com --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 8ed692989ccb..b814767786f2 100644 --- a/.mailmap +++ b/.mailmap @@ -166,6 +166,7 @@ Eduard-Mihai Burtescu Eduardo Bautista <=> Eduardo Bautista Eduardo Broto +Edward Shen Elliott Slaughter Elly Fong-Jones Eric Holk From f70f526eb10e530a3dd5593dc390570b2bd70066 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Feb 2023 09:10:39 +0100 Subject: [PATCH 135/137] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e0abc4bc9318..7bea079bb84b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f3126500f25114ba4e0ac3e76694dd45a22de56d +dffea43fc1102bdfe16d88ed412c23d4f0f08d9d From 601fc8b36b1962285e371cf3c54eeb3b1b9b3a74 Mon Sep 17 00:00:00 2001 From: Daniil Belov <70999565+BelovDV@users.noreply.github.com> Date: Thu, 26 Jan 2023 17:10:13 +0300 Subject: [PATCH 136/137] [link] enable packed bundled lib in non stable cases --- compiler/rustc_codegen_ssa/src/back/link.rs | 133 +++++------------- compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_codegen_ssa/src/lib.rs | 1 + .../locales/en-US/codegen_ssa.ftl | 2 +- compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_metadata/src/native_libs.rs | 27 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../Makefile | 35 +++++ .../rlib-format-packed-bundled-libs-3/main.rs | 5 + .../native_dep_1.c | 1 + .../native_dep_2.c | 1 + .../native_dep_3.c | 1 + .../native_dep_4.c | 1 + .../rust_dep.rs | 16 +++ .../rust_dep_cfg.rs | 10 ++ .../mix-bundle-and-whole-archive-link-attr.rs | 13 +- ...-bundle-and-whole-archive-link-attr.stderr | 6 +- .../mix-bundle-and-whole-archive.rs | 9 +- .../mix-bundle-and-whole-archive.stderr | 6 +- 19 files changed, 145 insertions(+), 126 deletions(-) create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/Makefile create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/main.rs create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4ac7bea03ebc..6fe8527ada62 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -270,10 +270,9 @@ pub fn each_linked_rlib( /// Create an 'rlib'. /// -/// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains -/// the object file of the crate, but it also contains all of the object files from native -/// libraries. This is done by unzipping native libraries and inserting all of the contents into -/// this archive. +/// An rlib in its current incarnation is essentially a renamed .a file (with "dummy" object files). +/// The rlib primarily contains the object file of the crate, but it also some of the object files +/// from native libraries. fn link_rlib<'a>( sess: &'a Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, @@ -347,44 +346,23 @@ fn link_rlib<'a>( // loaded from the libraries found here and then encode that into the // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { - match lib.kind { - NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } - if flavor == RlibFlavor::Normal && sess.opts.unstable_opts.packed_bundled_libs => {} - NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } - if flavor == RlibFlavor::Normal => - { - // Don't allow mixing +bundle with +whole_archive since an rlib may contain - // multiple native libs, some of which are +whole-archive and some of which are - // -whole-archive and it isn't clear how we can currently handle such a - // situation correctly. - // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897 - sess.emit_err(errors::IncompatibleLinkingModifiers); - } - NativeLibKind::Static { bundle: None | Some(true), .. } => {} - NativeLibKind::Static { bundle: Some(false), .. } - | NativeLibKind::Dylib { .. } - | NativeLibKind::Framework { .. } - | NativeLibKind::RawDylib - | NativeLibKind::LinkArg - | NativeLibKind::Unspecified => continue, + let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else { + continue; + }; + if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs { + sess.emit_err(errors::IncompatibleLinkingModifiers); } - if let Some(name) = lib.name { - let location = + if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename { + let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); + let src = read(path).map_err(|e| sess.emit_fatal(errors::ReadFileError {message: e }))?; + let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src); + let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); + packed_bundled_libs.push(wrapper_file); + } else if let Some(name) = lib.name { + let path = find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess); - if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal { - let filename = lib.filename.unwrap(); - let lib_path = - find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); - let src = read(lib_path) - .map_err(|e| sess.emit_fatal(errors::ReadFileError { message: e }))?; - let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src); - let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); - packed_bundled_libs.push(wrapper_file); - continue; - } - ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| { - sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error }); - }); + ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| { + sess.emit_fatal(errors::AddNativeLibrary { library_path: path, error })}); } } @@ -516,36 +494,14 @@ fn link_staticlib<'a>( &codegen_results.crate_info, Some(CrateType::Staticlib), &mut |cnum, path| { - let name = codegen_results.crate_info.crate_name[&cnum]; - let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; - - // Here when we include the rlib into our staticlib we need to make a - // decision whether to include the extra object files along the way. - // These extra object files come from statically included native - // libraries, but they may be cfg'd away with #[link(cfg(..))]. - // - // This unstable feature, though, only needs liblibc to work. The only - // use case there is where musl is statically included in liblibc.rlib, - // so if we don't want the included version we just need to skip it. As - // a result the logic here is that if *any* linked library is cfg'd away - // we just skip all object files. - // - // Clearly this is not sufficient for a general purpose feature, and - // we'd want to read from the library's metadata to determine which - // object files come from where and selectively skip them. - let skip_object_files = native_libs.iter().any(|lib| { - matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. }) - && !relevant_lib(sess, lib) - }); - let lto = are_upstream_rust_objects_already_included(sess) && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); - // Ignoring obj file starting with the crate name - // as simple comparison is not enough - there - // might be also an extra name suffix - let obj_start = name.as_str().to_owned(); + let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter(); + let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib)); + let relevant_libs: FxHashSet<_> = relevant.filter_map(|lib| lib.filename).collect(); + let bundled_libs: FxHashSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); ab.add_archive( path, Box::new(move |fname: &str| { @@ -559,20 +515,25 @@ fn link_staticlib<'a>( return true; } - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_object_files - && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) - { + // Skip objects for bundled libs. + if bundled_libs.contains(&Symbol::intern(fname)) { return true; } - // ok, don't skip this false }), ) .unwrap(); + archive_builder_builder + .extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs) + .unwrap_or_else(|e| sess.emit_fatal(e)); + for filename in relevant_libs { + let joined = tempdir.as_ref().join(filename.as_str()); + let path = joined.as_path(); + ab.add_archive(path, Box::new(|_| false)).unwrap(); + } + all_native_libs .extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); }, @@ -2590,18 +2551,8 @@ fn add_static_crate<'a>( cmd.link_rlib(&fix_windows_verbatim_for_gcc(path)); }; - // See the comment above in `link_staticlib` and `link_rlib` for why if - // there's a static library that's not relevant we skip all object - // files. - let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; - let skip_native = native_libs.iter().any(|lib| { - matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. }) - && !relevant_lib(sess, lib) - }); - - if (!are_upstream_rust_objects_already_included(sess) - || ignored_for_lto(sess, &codegen_results.crate_info, cnum)) - && !skip_native + if !are_upstream_rust_objects_already_included(sess) + || ignored_for_lto(sess, &codegen_results.crate_info, cnum) { link_upstream(cratepath); return; @@ -2632,17 +2583,13 @@ fn add_static_crate<'a>( let is_rust_object = canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); - // If we've been requested to skip all native object files - // (those not generated by the rust compiler) then we can skip - // this file. See above for why we may want to do this. - let skip_because_cfg_say_so = skip_native && !is_rust_object; - // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. - let skip_because_lto = - upstream_rust_objects_already_included && is_rust_object && is_builtins; + if upstream_rust_objects_already_included && is_rust_object && is_builtins { + return true; + } // We skip native libraries because: // 1. This native libraries won't be used from the generated rlib, @@ -2653,10 +2600,6 @@ fn add_static_crate<'a>( return true; } - if skip_because_cfg_say_so || skip_because_lto { - return true; - } - false }), ) { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 02b502d948c2..de2727c8a5dc 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -858,6 +858,7 @@ impl CrateInfo { dependency_formats: tcx.dependency_formats(()).clone(), windows_subsystem, natvis_debugger_visualizers: Default::default(), + feature_packed_bundled_libs: tcx.features().packed_bundled_libs, }; let crates = tcx.crates(()); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 0e6596d4ba78..d5530c476807 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -159,6 +159,7 @@ pub struct CrateInfo { pub dependency_formats: Lrc, pub windows_subsystem: Option, pub natvis_debugger_visualizers: BTreeSet, + pub feature_packed_bundled_libs: bool, // unstable feature flag. } #[derive(Encodable, Decodable)] diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 4924105128db..8fe5f8d50abe 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -22,7 +22,7 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} -codegen_ssa_incompatible_linking_modifiers = the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs +codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 323f5a368fc0..21d211eefbef 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -164,6 +164,8 @@ declare_features! ( (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None), /// Allows using `#[omit_gdb_pretty_printer_section]`. (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), + /// Allows using `+bundled,+whole-archive` native libs. + (active, packed_bundled_libs, "1.67.0", None, None), /// Allows using `#[prelude_import]` on glob `use` items. (active, prelude_import, "1.2.0", None, None), /// Used to identify crates that contain the profiler runtime. diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index e263fc748353..a8514c69d1c5 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -49,20 +49,21 @@ fn find_bundled_library( name: Option, verbatim: Option, kind: NativeLibKind, + has_cfg: bool, sess: &Session, ) -> Option { - if sess.opts.unstable_opts.packed_bundled_libs && - sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) && - let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind { - find_native_static_library( - name.unwrap().as_str(), - verbatim.unwrap_or(false), - &sess.target_filesearch(PathKind::Native).search_path_dirs(), - sess, - ).file_name().and_then(|s| s.to_str()).map(Symbol::intern) - } else { - None + if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind + && sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib)) + && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) + { + let verbatim = verbatim.unwrap_or(false); + let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs(); + return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess) + .file_name() + .and_then(|s| s.to_str()) + .map(Symbol::intern); } + None } pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { @@ -385,7 +386,7 @@ impl<'tcx> Collector<'tcx> { let name = name.map(|(name, _)| name); let kind = kind.unwrap_or(NativeLibKind::Unspecified); - let filename = find_bundled_library(name, verbatim, kind, sess); + let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess); self.libs.push(NativeLib { name, filename, @@ -475,7 +476,7 @@ impl<'tcx> Collector<'tcx> { let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))); let sess = self.tcx.sess; let filename = - find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess); + find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess); self.libs.push(NativeLib { name, filename, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f1119214be44..1933360f722a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1049,6 +1049,7 @@ symbols! { overlapping_marker_traits, owned_box, packed, + packed_bundled_libs, panic, panic_2015, panic_2021, diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile new file mode 100644 index 000000000000..62dc1b5f6060 --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile @@ -0,0 +1,35 @@ +-include ../../run-make-fulldeps/tools.mk + +# ignore-cross-compile +# only-linux + +# Make sure -Zpacked_bundled_libs-like behavior activates with whole-archive. + +# We're using the llvm-nm instead of the system nm to ensure it is compatible +# with the LLVM bitcode generated by rustc. +NM = "$(LLVM_BIN_DIR)"/llvm-nm + +all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) $(call NATIVE_STATICLIB,native_dep_4) + # test cfg with packed bundle + $(RUSTC) rust_dep_cfg.rs --crate-type=rlib -Zpacked_bundled_libs + $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep_cfg.rlib --crate-type=staticlib --cfg should_add + $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_1.a" + $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_2.a" + $(AR) t $(TMPDIR)/libmain.a | $(CGREP) -e "libnative_dep_1.o" + $(AR) t $(TMPDIR)/libmain.a | $(CGREP) -ev "libnative_dep_2.o" + + + # test bundle with whole_archive + $(RUSTC) rust_dep.rs --crate-type=rlib + $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_1" + $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_3" + $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_2" + $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_4" + + # Make sure compiler doesn't use files, that it shouldn't know about. + rm $(TMPDIR)/libnative_dep_1.a + rm $(TMPDIR)/libnative_dep_3.a + + $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib --print link-args > $(TMPDIR)/link_args + cat $(TMPDIR)/link_args | $(CGREP) -ev "native_dep_3" + cat $(TMPDIR)/link_args | $(CGREP) -e "--whole-archive.*native_dep_1.*--whole-archive.*lnative_dep_2.*no-whole-archive.*lnative_dep_4" diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs new file mode 100644 index 000000000000..8d2b8a2859c0 --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs @@ -0,0 +1,5 @@ +extern crate rust_dep; + +pub fn main() { + rust_dep::rust_dep(); +} diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c new file mode 100644 index 000000000000..07be8562c928 --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c @@ -0,0 +1 @@ +int native_f1() { return 1; } diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c new file mode 100644 index 000000000000..a1b94e40dc04 --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c @@ -0,0 +1 @@ +int native_f2() { return 2; } diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c new file mode 100644 index 000000000000..f81f397a4b1d --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c @@ -0,0 +1 @@ +int native_f3() { return 3; } diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c new file mode 100644 index 000000000000..14d41d60b1fe --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c @@ -0,0 +1 @@ +int native_f4() { return 4; } diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs new file mode 100644 index 000000000000..abd846b6862d --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs @@ -0,0 +1,16 @@ +#![feature(packed_bundled_libs)] + +#[link(name = "native_dep_1", kind = "static", modifiers = "+whole-archive,+bundle")] +extern "C" {} + +#[link(name = "native_dep_2", kind = "static", modifiers = "+whole-archive,-bundle")] +extern "C" {} + +#[link(name = "native_dep_3", kind = "static", modifiers = "+bundle")] +extern "C" {} + +#[link(name = "native_dep_4", kind = "static", modifiers = "-bundle")] +extern "C" {} + +#[no_mangle] +pub fn rust_dep() {} diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs new file mode 100644 index 000000000000..506ca62a8a6b --- /dev/null +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs @@ -0,0 +1,10 @@ +#![feature(link_cfg)] + +#[link(name = "native_dep_1", kind = "static", cfg(should_add))] +extern "C" {} + +#[link(name = "native_dep_2", kind = "static", cfg(should_not_add))] +extern "C" {} + +#[no_mangle] +pub fn rust_dep() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs index 066048795c8a..0ccd441cc648 100644 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs @@ -1,8 +1,11 @@ -// compile-flags: -Zunstable-options --crate-type rlib +// gate-test-packed_bundled_libs + +// ignore-wasm32-bare +// compile-flags: --crate-type rlib +// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs // build-fail -// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs -#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")] -extern "C" { } +#[link(name = "rust_test_helpers", kind = "static", modifiers = "+bundle,+whole-archive")] +extern "C" {} -fn main() { } +fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr index 246efb8d627c..8a9fed740b04 100644 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr @@ -1,6 +1,4 @@ -error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs +error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -error: could not find native static library `mylib`, perhaps an -L flag is missing? - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs index 1d0768d99cff..18d4b52a34c3 100644 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs @@ -1,7 +1,8 @@ -// Mixing +bundle and +whole-archive is not allowed +// gate-test-packed_bundled_libs -// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib +// ignore-wasm32-bare +// compile-flags: -l static:+bundle,+whole-archive=rust_test_helpers --crate-type rlib +// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs // build-fail -// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs -fn main() { } +fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr index 246efb8d627c..8a9fed740b04 100644 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr @@ -1,6 +1,4 @@ -error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs +error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -error: could not find native static library `mylib`, perhaps an -L flag is missing? - -error: aborting due to 2 previous errors +error: aborting due to previous error From 8461c0eb673e769cae656ce52dd662829437e200 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Feb 2023 10:33:19 +0100 Subject: [PATCH 137/137] fmt --- src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 106e93751d21..4e6ff28d6ec7 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -148,8 +148,7 @@ impl NewPermission { NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), - protector: (kind == RetagKind::FnEntry) - .then_some(ProtectorKind::WeakProtector), + protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), } } else { // `!Unpin` boxes do not get `noalias` nor `dereferenceable`.