From 9691ad027433d5d22418d6dd8cbf4ed09a2d38b8 Mon Sep 17 00:00:00 2001 From: John Heitmann Date: Thu, 27 Dec 2018 18:18:16 -0800 Subject: [PATCH 001/124] Fix all non-bug lints This change fixes all non-bug lints. A few lint rules are tweaked, and a few code lines are tweaked (almost all dead code elimination). Also, update the rustdoc-js tester in anticipation of let/const statements. --- src/librustdoc/html/static/.eslintrc.js | 6 +++++- src/librustdoc/html/static/main.js | 18 ++++++------------ src/librustdoc/html/static/settings.js | 3 +++ src/librustdoc/html/static/source-script.js | 3 +++ src/librustdoc/html/static/storage.js | 3 +++ src/tools/rustdoc-js/tester.js | 8 ++++---- 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index c7af41ac969ce..3e1114f9c9ce8 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": 2015, - "sourceType": "module" + "sourceType": "script" }, "rules": { "linebreak-style": [ @@ -16,6 +16,10 @@ module.exports = { "semi": [ "error", "always" + ], + "no-constant-condition": [ + "error", + { "checkLoops": false } ] } }; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 75b0f5df0d8b3..63dfe79412a09 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,9 +1,12 @@ // From rust: /* global ALIASES, currentCrate, rootPath */ +// From DOM global ids: +/* global help */ + // Local js definitions: /* global addClass, getCurrentValue, hasClass */ -/* global isHidden onEach, removeClass, updateLocalStorage */ +/* global isHidden, onEachLazy, removeClass, updateLocalStorage */ if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { @@ -79,8 +82,6 @@ if (!DOMTokenList.prototype.remove) { // 2 for "In Return Types" var currentTab = 0; - var themesWidth = null; - var titleBeforeSearch = document.title; function getPageId() { @@ -378,7 +379,7 @@ if (!DOMTokenList.prototype.remove) { len = rootPath.match(/\.\.\//g).length + 1; for (i = 0; i < len; ++i) { - match = url.match(/\/[^\/]*$/); + match = url.match(/\/[^/]*$/); if (i < len - 1) { stripped = match[0] + stripped; } @@ -631,8 +632,6 @@ if (!DOMTokenList.prototype.remove) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length >= val.generics.length) { var elems = obj[GENERICS_DATA].slice(0); - var total = 0; - var done = 0; // We need to find the type that matches the most to remove it in order // to move forward. var vlength = val.generics.length; @@ -649,8 +648,6 @@ if (!DOMTokenList.prototype.remove) { if (lev.pos !== -1) { elems.splice(lev.pos, 1); lev_distance = Math.min(lev.lev, lev_distance); - total += lev.lev; - done += 1; } else { return MAX_LEV_DISTANCE + 1; } @@ -912,7 +909,6 @@ if (!DOMTokenList.prototype.remove) { fullId = generateId(ty); // allow searching for void (no output) functions as well - var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : ""; returned = checkReturned(ty, output, true); if (output.name === "*" || returned === true) { in_args = false; @@ -959,7 +955,7 @@ if (!DOMTokenList.prototype.remove) { query.output = val; query.search = val; // gather matching search results up to a certain maximum - val = val.replace(/\_/g, ""); + val = val.replace(/_/g, ""); var valGenerics = extractGenerics(val); @@ -976,12 +972,10 @@ if (!DOMTokenList.prototype.remove) { for (j = 0; j < nSearchWords; ++j) { var lev; - var lev_distance; ty = searchIndex[j]; if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) { continue; } - var lev_distance; var lev_add = 0; if (paths.length > 1) { lev = checkPath(contains, paths[paths.length - 1], ty); diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js index c21db7371f3c3..427a74c0c87fa 100644 --- a/src/librustdoc/html/static/settings.js +++ b/src/librustdoc/html/static/settings.js @@ -1,3 +1,6 @@ +// Local js definitions: +/* global getCurrentValue, updateLocalStorage */ + (function () { function changeSetting(settingName, isEnabled) { updateLocalStorage('rustdoc-' + settingName, isEnabled); diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 0affe1c6812f5..6ef70fb7d3502 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -1,6 +1,9 @@ // From rust: /* global sourcesIndex */ +// From DOM global ids: +/* global search */ + // Local js definitions: /* global addClass, getCurrentValue, hasClass, removeClass, updateLocalStorage */ diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index d5dea247d28d1..27b6f40d797f3 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -1,6 +1,9 @@ // From rust: /* global resourcesSuffix */ +// eslint doesn't understand the functions here are used elsewhere +/*eslint no-unused-vars: "off"*/ + var currentTheme = document.getElementById("themeStyle"); var mainTheme = document.getElementById("mainThemeStyle"); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c41da93a98310..7150241ee4dba 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -81,9 +81,9 @@ function extractFunction(content, functionName) { // Stupid function extractor for array. function extractArrayVariable(content, arrayName) { - var splitter = "var " + arrayName; + var splitter = new RegExp("(?:var|const|let) " + arrayName); while (true) { - var start = content.indexOf(splitter); + var start = content.search(splitter); if (start === -1) { break; } @@ -126,9 +126,9 @@ function extractArrayVariable(content, arrayName) { // Stupid function extractor for variable. function extractVariable(content, varName) { - var splitter = "var " + varName; + var splitter = new RegExp("(?:var|const|let) " + varName); while (true) { - var start = content.indexOf(splitter); + var start = content.search(splitter); if (start === -1) { break; } From 2878ab8c4b34df4efee5710deaf3b31d0862a48f Mon Sep 17 00:00:00 2001 From: John Heitmann Date: Tue, 18 Dec 2018 12:18:42 -0800 Subject: [PATCH 002/124] Use let instead of var, except for globals. --- src/librustdoc/html/static/main.js | 606 ++++++++++---------- src/librustdoc/html/static/settings.js | 10 +- src/librustdoc/html/static/source-script.js | 44 +- src/librustdoc/html/static/storage.js | 14 +- 4 files changed, 337 insertions(+), 337 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 63dfe79412a09..29fa67bac3ae7 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -16,7 +16,7 @@ if (!String.prototype.startsWith) { } if (!String.prototype.endsWith) { String.prototype.endsWith = function(suffix, length) { - var l = length || this.length; + let l = length || this.length; return this.indexOf(suffix, l - suffix.length) !== -1; }; } @@ -47,7 +47,7 @@ if (!DOMTokenList.prototype.remove) { // This mapping table should match the discriminants of // `rustdoc::html::item_type::ItemType` type in Rust. - var itemTypes = ["mod", + let itemTypes = ["mod", "externcrate", "import", "struct", @@ -73,19 +73,19 @@ if (!DOMTokenList.prototype.remove) { "attr", "derive"]; - var search_input = document.getElementsByClassName("search-input")[0]; + let search_input = document.getElementsByClassName("search-input")[0]; // On the search screen, so you remain on the last tab you opened. // // 0 for "In Names" // 1 for "In Parameters" // 2 for "In Return Types" - var currentTab = 0; + let currentTab = 0; - var titleBeforeSearch = document.title; + let titleBeforeSearch = document.title; function getPageId() { - var id = document.location.href.split("#")[1]; + let id = document.location.href.split("#")[1]; if (id) { return id.split("?")[0].split("&")[0]; } @@ -93,57 +93,57 @@ if (!DOMTokenList.prototype.remove) { } function showSidebar() { - var elems = document.getElementsByClassName("sidebar-elems")[0]; + let elems = document.getElementsByClassName("sidebar-elems")[0]; if (elems) { addClass(elems, "show-it"); } - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; if (sidebar) { addClass(sidebar, "mobile"); - var filler = document.getElementById("sidebar-filler"); + let filler = document.getElementById("sidebar-filler"); if (!filler) { - var div = document.createElement("div"); + let div = document.createElement("div"); div.id = "sidebar-filler"; sidebar.appendChild(div); } } - var themePicker = document.getElementsByClassName("theme-picker"); + let themePicker = document.getElementsByClassName("theme-picker"); if (themePicker && themePicker.length > 0) { themePicker[0].style.display = "none"; } } function hideSidebar() { - var elems = document.getElementsByClassName("sidebar-elems")[0]; + let elems = document.getElementsByClassName("sidebar-elems")[0]; if (elems) { removeClass(elems, "show-it"); } - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; removeClass(sidebar, "mobile"); - var filler = document.getElementById("sidebar-filler"); + let filler = document.getElementById("sidebar-filler"); if (filler) { filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ""; - var themePicker = document.getElementsByClassName("theme-picker"); + let themePicker = document.getElementsByClassName("theme-picker"); if (themePicker && themePicker.length > 0) { themePicker[0].style.display = null; } } // used for special search precedence - var TY_PRIMITIVE = itemTypes.indexOf("primitive"); - var TY_KEYWORD = itemTypes.indexOf("keyword"); + let TY_PRIMITIVE = itemTypes.indexOf("primitive"); + let TY_KEYWORD = itemTypes.indexOf("keyword"); onEachLazy(document.getElementsByClassName("js-only"), function(e) { removeClass(e, "js-only"); }); function getQueryStringParams() { - var params = {}; + let params = {}; window.location.search.substring(1).split("&"). map(function(s) { - var pair = s.split("="); + let pair = s.split("="); params[decodeURIComponent(pair[0])] = typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]); }); @@ -155,14 +155,14 @@ if (!DOMTokenList.prototype.remove) { window.history && typeof window.history.pushState === "function"; } - var main = document.getElementById("main"); + let main = document.getElementById("main"); function highlightSourceLines(ev) { // If we're in mobile mode, we should add the sidebar in any case. hideSidebar(); - var elem; - var search = document.getElementById("search"); - var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); + let elem; + let search = document.getElementById("search"); + let i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { from = parseInt(match[1], 10); to = Math.min(50000, parseInt(match[2] || match[1], 10)); @@ -172,7 +172,7 @@ if (!DOMTokenList.prototype.remove) { return; } if (ev === null) { - var x = document.getElementById(from); + let x = document.getElementById(from); if (x) { x.scrollIntoView(); } @@ -188,7 +188,7 @@ if (!DOMTokenList.prototype.remove) { } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { addClass(search, "hidden"); removeClass(main, "hidden"); - var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); + let hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); if (browserSupportsHistoryApi()) { history.replaceState(hash, "", "?search=#" + hash); } @@ -200,15 +200,15 @@ if (!DOMTokenList.prototype.remove) { } function expandSection(id) { - var elem = document.getElementById(id); + let elem = document.getElementById(id); if (elem && isHidden(elem)) { - var h3 = elem.parentNode.previousElementSibling; + let h3 = elem.parentNode.previousElementSibling; if (h3 && h3.tagName !== "H3") { h3 = h3.previousElementSibling; // skip div.docblock } if (h3) { - var collapses = h3.getElementsByClassName("collapse-toggle"); + let collapses = h3.getElementsByClassName("collapse-toggle"); if (collapses.length > 0) { // The element is not visible, we need to make it appear! collapseDocs(collapses[0], "show"); @@ -235,7 +235,7 @@ if (!DOMTokenList.prototype.remove) { return ev.key; } - var c = ev.charCode || ev.keyCode; + let c = ev.charCode || ev.keyCode; if (c == 27) { return "Escape"; } @@ -258,7 +258,7 @@ if (!DOMTokenList.prototype.remove) { function handleEscape(ev, help) { hideModal(); - var search = document.getElementById("search"); + let search = document.getElementById("search"); if (hasClass(help, "hidden") === false) { displayHelp(false, ev); } else if (hasClass(search, "hidden") === false) { @@ -276,7 +276,7 @@ if (!DOMTokenList.prototype.remove) { return; } - var help = document.getElementById("help"); + let help = document.getElementById("help"); if (document.activeElement.tagName === "INPUT") { switch (getVirtualKey(ev)) { case "Escape": @@ -331,9 +331,9 @@ if (!DOMTokenList.prototype.remove) { } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { collapseDocs(ev.target.parentNode, "toggle"); } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { - var prev_id = 0; + let prev_id = 0; - var set_fragment = function(name) { + let set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, "#" + name); window.hashchange(); @@ -342,11 +342,11 @@ if (!DOMTokenList.prototype.remove) { } }; - var cur_id = parseInt(ev.target.id, 10); + let cur_id = parseInt(ev.target.id, 10); if (ev.shiftKey && prev_id) { if (prev_id > cur_id) { - var tmp = prev_id; + let tmp = prev_id; prev_id = cur_id; cur_id = tmp; } @@ -363,17 +363,17 @@ if (!DOMTokenList.prototype.remove) { } else { // Making a collapsed element visible on onhashchange seems // too late - var a = findParentElement(ev.target, "A"); + let a = findParentElement(ev.target, "A"); if (a && a.hash) { expandSection(a.hash.replace(/^#/, "")); } } }; - var x = document.getElementsByClassName("version-selector"); + let x = document.getElementsByClassName("version-selector"); if (x.length > 0) { x[0].onchange = function() { - var i, match, + let i, match, url = document.location.href, stripped = "", len = rootPath.match(/\.\.\//g).length + 1; @@ -399,14 +399,14 @@ if (!DOMTokenList.prototype.remove) { * This code is an unmodified version of the code written by Marco de Wit * and was found at http://stackoverflow.com/a/18514751/745719 */ - var levenshtein_row2 = []; + let levenshtein_row2 = []; function levenshtein(s1, s2) { if (s1 === s2) { return 0; } - var s1_len = s1.length, s2_len = s2.length; + let s1_len = s1.length, s2_len = s2.length; if (s1_len && s2_len) { - var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2; + let i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2; while (i1 < s1_len) { row[i1] = ++i1; } @@ -428,14 +428,14 @@ if (!DOMTokenList.prototype.remove) { } function initSearch(rawSearchIndex) { - var currentResults, index, searchIndex; - var MAX_LEV_DISTANCE = 3; - var MAX_RESULTS = 200; - var GENERICS_DATA = 1; - var NAME = 0; - var INPUTS_DATA = 0; - var OUTPUT_DATA = 1; - var params = getQueryStringParams(); + let currentResults, index, searchIndex; + let MAX_LEV_DISTANCE = 3; + let MAX_RESULTS = 200; + let GENERICS_DATA = 1; + let NAME = 0; + let INPUTS_DATA = 0; + let OUTPUT_DATA = 1; + let params = getQueryStringParams(); // Populate search bar with query string search term when provided, // but only if the input bar is empty. This avoid the obnoxious issue @@ -455,8 +455,8 @@ if (!DOMTokenList.prototype.remove) { */ function execQuery(query, searchWords, filterCrates) { function itemTypeFromName(typename) { - var length = itemTypes.length; - for (var i = 0; i < length; ++i) { + let length = itemTypes.length; + for (let i = 0; i < length; ++i) { if (itemTypes[i] === typename) { return i; } @@ -464,14 +464,14 @@ if (!DOMTokenList.prototype.remove) { return -1; } - var valLower = query.query.toLowerCase(), + let valLower = query.query.toLowerCase(), val = valLower, typeFilter = itemTypeFromName(query.type), results = {}, results_in_args = {}, results_returned = {}, split = valLower.split("::"); - var length = split.length; - for (var z = 0; z < length; ++z) { + let length = split.length; + for (let z = 0; z < length; ++z) { if (split[z] === "") { split.splice(z, 1); z -= 1; @@ -479,14 +479,14 @@ if (!DOMTokenList.prototype.remove) { } function transformResults(results, isType) { - var out = []; - var length = results.length; - for (var i = 0; i < length; ++i) { + let out = []; + let length = results.length; + for (let i = 0; i < length; ++i) { if (results[i].id > -1) { - var obj = searchIndex[results[i].id]; + let obj = searchIndex[results[i].id]; obj.lev = results[i].lev; if (isType !== true || obj.type) { - var res = buildHrefAndPath(obj); + let res = buildHrefAndPath(obj); obj.displayPath = pathSplitter(res[0]); obj.fullPath = obj.displayPath + obj.name; // To be sure than it some items aren't considered as duplicate. @@ -503,15 +503,15 @@ if (!DOMTokenList.prototype.remove) { } function sortResults(results, isType) { - var ar = []; - for (var entry in results) { + let ar = []; + for (let entry in results) { if (results.hasOwnProperty(entry)) { ar.push(results[entry]); } } results = ar; - var i; - var nresults = results.length; + let i; + let nresults = results.length; for (i = 0; i < nresults; ++i) { results[i].word = searchWords[results[i].id]; results[i].item = searchIndex[results[i].id] || {}; @@ -522,7 +522,7 @@ if (!DOMTokenList.prototype.remove) { } results.sort(function(aaa, bbb) { - var a, b; + let a, b; // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) @@ -588,15 +588,15 @@ if (!DOMTokenList.prototype.remove) { return 0; }); - var length = results.length; + let length = results.length; for (i = 0; i < length; ++i) { - var result = results[i]; + let result = results[i]; // this validation does not make sense when searching by types if (result.dontValidate) { continue; } - var name = result.item.name.toLowerCase(), + let name = result.item.name.toLowerCase(), path = result.item.path.toLowerCase(), parent = result.item.parent; @@ -612,7 +612,7 @@ if (!DOMTokenList.prototype.remove) { function extractGenerics(val) { val = val.toLowerCase(); if (val.indexOf("<") !== -1) { - var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">")); + let values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">")); return { name: val.substring(0, val.indexOf("<")), generics: values.split(/\s*,\s*/), @@ -627,19 +627,19 @@ if (!DOMTokenList.prototype.remove) { function checkGenerics(obj, val) { // The names match, but we need to be sure that all generics kinda // match as well. - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (val.generics.length > 0) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length >= val.generics.length) { - var elems = obj[GENERICS_DATA].slice(0); + let elems = obj[GENERICS_DATA].slice(0); // We need to find the type that matches the most to remove it in order // to move forward. - var vlength = val.generics.length; - for (var y = 0; y < vlength; ++y) { - var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; - var elength = elems.length; - for (var x = 0; x < elength; ++x) { - var tmp_lev = levenshtein(elems[x], val.generics[y]); + let vlength = val.generics.length; + for (let y = 0; y < vlength; ++y) { + let lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; + let elength = elems.length; + for (let x = 0; x < elength; ++x) { + let tmp_lev = levenshtein(elems[x], val.generics[y]); if (tmp_lev < lev.lev) { lev.lev = tmp_lev; lev.pos = x; @@ -660,17 +660,17 @@ if (!DOMTokenList.prototype.remove) { // Check for type name and type generics (if any). function checkType(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; - var x; + let lev_distance = MAX_LEV_DISTANCE + 1; + let x; if (obj[NAME] === val.name) { if (literalSearch === true) { if (val.generics && val.generics.length !== 0) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length >= val.generics.length) { - var elems = obj[GENERICS_DATA].slice(0); - var allFound = true; + let elems = obj[GENERICS_DATA].slice(0); + let allFound = true; - for (var y = 0; allFound === true && y < val.generics.length; ++y) { + for (let y = 0; allFound === true && y < val.generics.length; ++y) { allFound = false; for (x = 0; allFound === false && x < elems.length; ++x) { allFound = elems[x] === val.generics[y]; @@ -691,7 +691,7 @@ if (!DOMTokenList.prototype.remove) { // If the type has generics but don't match, then it won't return at this point. // Otherwise, `checkGenerics` will return 0 and it'll return. if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { - var tmp_lev = checkGenerics(obj, val); + let tmp_lev = checkGenerics(obj, val); if (tmp_lev <= MAX_LEV_DISTANCE) { return tmp_lev; } @@ -702,7 +702,7 @@ if (!DOMTokenList.prototype.remove) { // Names didn't match so let's check if one of the generic types could. if (literalSearch === true) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { - var length = obj[GENERICS_DATA].length; + let length = obj[GENERICS_DATA].length; for (x = 0; x < length; ++x) { if (obj[GENERICS_DATA][x] === val.name) { return true; @@ -716,7 +716,7 @@ if (!DOMTokenList.prototype.remove) { lev_distance = Math.min(checkGenerics(obj, val), lev_distance); } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { // We can check if the type we're looking for is inside the generics! - var olength = obj[GENERICS_DATA].length; + let olength = obj[GENERICS_DATA].length; for (x = 0; x < olength; ++x) { lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name), lev_distance); @@ -728,13 +728,13 @@ if (!DOMTokenList.prototype.remove) { } function findArg(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) { - var length = obj.type[INPUTS_DATA].length; - for (var i = 0; i < length; i++) { - var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); + let length = obj.type[INPUTS_DATA].length; + for (let i = 0; i < length; i++) { + let tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -748,10 +748,10 @@ if (!DOMTokenList.prototype.remove) { } function checkReturned(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type.length > OUTPUT_DATA) { - var tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch); + let tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -767,26 +767,26 @@ if (!DOMTokenList.prototype.remove) { if (contains.length === 0) { return 0; } - var ret_lev = MAX_LEV_DISTANCE + 1; - var path = ty.path.split("::"); + let ret_lev = MAX_LEV_DISTANCE + 1; + let path = ty.path.split("::"); if (ty.parent && ty.parent.name) { path.push(ty.parent.name.toLowerCase()); } - var length = path.length; - var clength = contains.length; + let length = path.length; + let clength = contains.length; if (clength > length) { return MAX_LEV_DISTANCE + 1; } - for (var i = 0; i < length; ++i) { + for (let i = 0; i < length; ++i) { if (i + clength > length) { break; } - var lev_total = 0; - var aborted = false; - for (var x = 0; x < clength; ++x) { - var lev = levenshtein(path[i + x], contains[x]); + let lev_total = 0; + let aborted = false; + for (let x = 0; x < clength; ++x) { + let lev = levenshtein(path[i + x], contains[x]); if (lev > MAX_LEV_DISTANCE) { aborted = true; break; @@ -808,7 +808,7 @@ if (!DOMTokenList.prototype.remove) { if (filter === type) return true; // Match related items - var name = itemTypes[type]; + let name = itemTypes[type]; switch (itemTypes[filter]) { case "constant": return (name == "associatedconstant"); @@ -830,12 +830,12 @@ if (!DOMTokenList.prototype.remove) { } // quoted values mean literal search - var nSearchWords = searchWords.length; - var i; - var ty; - var fullId; - var returned; - var in_args; + let nSearchWords = searchWords.length; + let i; + let ty; + let fullId; + let returned; + let in_args; if ((val.charAt(0) === "\"" || val.charAt(0) === "'") && val.charAt(val.length - 1) === val.charAt(0)) { @@ -887,21 +887,21 @@ if (!DOMTokenList.prototype.remove) { query.search = val; // searching by type } else if (val.search("->") > -1) { - var trimmer = function(s) { return s.trim(); }; - var parts = val.split("->").map(trimmer); - var input = parts[0]; + let trimmer = function(s) { return s.trim(); }; + let parts = val.split("->").map(trimmer); + let input = parts[0]; // sort inputs so that order does not matter - var inputs = input.split(",").map(trimmer).sort(); + let inputs = input.split(",").map(trimmer).sort(); for (i = 0; i < inputs.length; ++i) { inputs[i] = extractGenerics(inputs[i]); } - var output = extractGenerics(parts[1]); + let output = extractGenerics(parts[1]); for (i = 0; i < nSearchWords; ++i) { if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) { continue; } - var type = searchIndex[i].type; + let type = searchIndex[i].type; ty = searchIndex[i]; if (!type) { continue; @@ -912,13 +912,13 @@ if (!DOMTokenList.prototype.remove) { returned = checkReturned(ty, output, true); if (output.name === "*" || returned === true) { in_args = false; - var module = false; + let module = false; if (input === "*") { module = true; } else { - var allFound = true; - for (var it = 0; allFound === true && it < inputs.length; it++) { + let allFound = true; + for (let it = 0; allFound === true && it < inputs.length; it++) { allFound = checkType(type, inputs[it], true); } in_args = allFound; @@ -957,10 +957,10 @@ if (!DOMTokenList.prototype.remove) { // gather matching search results up to a certain maximum val = val.replace(/_/g, ""); - var valGenerics = extractGenerics(val); + let valGenerics = extractGenerics(val); - var paths = valLower.split("::"); - var j; + let paths = valLower.split("::"); + let j; for (j = 0; j < paths.length; ++j) { if (paths[j] === "") { paths.splice(j, 1); @@ -968,15 +968,15 @@ if (!DOMTokenList.prototype.remove) { } } val = paths[paths.length - 1]; - var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1); + let contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1); for (j = 0; j < nSearchWords; ++j) { - var lev; + let lev; ty = searchIndex[j]; if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) { continue; } - var lev_add = 0; + let lev_add = 0; if (paths.length > 1) { lev = checkPath(contains, paths[paths.length - 1], ty); if (lev > MAX_LEV_DISTANCE) { @@ -988,7 +988,7 @@ if (!DOMTokenList.prototype.remove) { returned = MAX_LEV_DISTANCE + 1; in_args = MAX_LEV_DISTANCE + 1; - var index = -1; + let index = -1; // we want lev results to go lower than others lev = MAX_LEV_DISTANCE + 1; fullId = generateId(ty); @@ -1066,19 +1066,19 @@ if (!DOMTokenList.prototype.remove) { } } - var ret = { + let ret = { "in_args": sortResults(results_in_args, true), "returned": sortResults(results_returned, true), "others": sortResults(results), }; if (ALIASES && ALIASES[window.currentCrate] && ALIASES[window.currentCrate][query.raw]) { - var aliases = ALIASES[window.currentCrate][query.raw]; + let aliases = ALIASES[window.currentCrate][query.raw]; for (i = 0; i < aliases.length; ++i) { aliases[i].is_alias = true; aliases[i].alias = query.raw; aliases[i].path = aliases[i].p; - var res = buildHrefAndPath(aliases[i]); + let res = buildHrefAndPath(aliases[i]); aliases[i].displayPath = pathSplitter(res[0]); aliases[i].fullPath = aliases[i].displayPath + aliases[i].name; aliases[i].href = res[1]; @@ -1107,7 +1107,7 @@ if (!DOMTokenList.prototype.remove) { * @return {[boolean]} [Whether the result is valid or not] */ function validateResult(name, path, keys, parent) { - for (var i = 0; i < keys.length; ++i) { + for (let i = 0; i < keys.length; ++i) { // each check is for validation so we negate the conditions and invalidate if (!( // check for an exact name match @@ -1126,7 +1126,7 @@ if (!DOMTokenList.prototype.remove) { } function getQuery(raw) { - var matches, type, query; + let matches, type, query; query = raw; matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i); @@ -1144,15 +1144,15 @@ if (!DOMTokenList.prototype.remove) { } function initSearchNav() { - var hoverTimeout; + let hoverTimeout; - var click_func = function(e) { - var el = e.target; + let click_func = function(e) { + let el = e.target; // to retrieve the real "owner" of the event. while (el.tagName !== "TR") { el = el.parentNode; } - var dst = e.target.getElementsByTagName("a"); + let dst = e.target.getElementsByTagName("a"); if (dst.length < 1) { return; } @@ -1163,8 +1163,8 @@ if (!DOMTokenList.prototype.remove) { document.location.href = dst.href; } }; - var mouseover_func = function(e) { - var el = e.target; + let mouseover_func = function(e) { + let el = e.target; // to retrieve the real "owner" of the event. while (el.tagName !== "TR") { el = el.parentNode; @@ -1189,9 +1189,9 @@ if (!DOMTokenList.prototype.remove) { search_input.onkeydown = function(e) { // "actives" references the currently highlighted item in each search tab. // Each array in "actives" represents a tab. - var actives = [[], [], []]; + let actives = [[], [], []]; // "current" is used to know which tab we're looking into. - var current = 0; + let current = 0; onEachLazy(document.getElementsByClassName("search-results"), function(e) { onEachLazy(e.getElementsByClassName("highlighted"), function(e) { actives[current].push(e); @@ -1209,9 +1209,9 @@ if (!DOMTokenList.prototype.remove) { removeClass(actives[currentTab][0], "highlighted"); } else if (e.which === 40) { // down if (!actives[currentTab].length) { - var results = document.getElementsByClassName("search-results"); + let results = document.getElementsByClassName("search-results"); if (results.length > 0) { - var res = results[currentTab].getElementsByClassName("result"); + let res = results[currentTab].getElementsByClassName("result"); if (res.length > 0) { addClass(res[0], "highlighted"); } @@ -1245,10 +1245,10 @@ if (!DOMTokenList.prototype.remove) { } function buildHrefAndPath(item) { - var displayPath; - var href; - var type = itemTypes[item.ty]; - var name = item.name; + let displayPath; + let href; + let type = itemTypes[item.ty]; + let name = item.name; if (type === "mod") { displayPath = item.path + "::"; @@ -1262,9 +1262,9 @@ if (!DOMTokenList.prototype.remove) { displayPath = ""; href = rootPath + name + "/index.html"; } else if (item.parent !== undefined) { - var myparent = item.parent; - var anchor = "#" + type + "." + name; - var parentType = itemTypes[myparent.ty]; + let myparent = item.parent; + let anchor = "#" + type + "." + name; + let parentType = itemTypes[myparent.ty]; if (parentType === "primitive") { displayPath = myparent.name + "::"; } else { @@ -1283,13 +1283,13 @@ if (!DOMTokenList.prototype.remove) { } function escape(content) { - var h1 = document.createElement("h1"); + let h1 = document.createElement("h1"); h1.textContent = content; return h1.innerHTML; } function pathSplitter(path) { - var tmp = "" + path.replace(/::/g, "::"); + let tmp = "" + path.replace(/::/g, "::"); if (tmp.endsWith("")) { return tmp.slice(0, tmp.length - 6); } @@ -1297,19 +1297,19 @@ if (!DOMTokenList.prototype.remove) { } function addTab(array, query, display) { - var extraStyle = ""; + let extraStyle = ""; if (display === false) { extraStyle = " style=\"display: none;\""; } - var output = ""; - var duplicates = {}; - var length = 0; + let output = ""; + let duplicates = {}; + let length = 0; if (array.length > 0) { output = ""; array.forEach(function(item) { - var name, type; + let name, type; name = item.name; type = itemTypes[item.ty]; @@ -1363,22 +1363,22 @@ if (!DOMTokenList.prototype.remove) { function showResults(results) { if (results.others.length === 1 && getCurrentValue("rustdoc-go-to-only-result") === "true") { - var elem = document.createElement("a"); + let elem = document.createElement("a"); elem.href = results.others[0].href; elem.style.display = "none"; // For firefox, we need the element to be in the DOM so it can be clicked. document.body.appendChild(elem); elem.click(); } - var query = getQuery(search_input.value); + let query = getQuery(search_input.value); currentResults = query.id; - var ret_others = addTab(results.others, query); - var ret_in_args = addTab(results.in_args, query, false); - var ret_returned = addTab(results.returned, query, false); + let ret_others = addTab(results.others, query); + let ret_in_args = addTab(results.in_args, query, false); + let ret_returned = addTab(results.returned, query, false); - var output = "

Results for " + escape(query.query) + + let output = "

Results for " + escape(query.query) + (query.type ? " (type: " + escape(query.type) + ")" : "") + "

" + "
" + makeTabHeader(0, "In Names", ret_others[1]) + @@ -1388,20 +1388,20 @@ if (!DOMTokenList.prototype.remove) { ret_others[0] + ret_in_args[0] + ret_returned[0] + "
"; addClass(main, "hidden"); - var search = document.getElementById("search"); + let search = document.getElementById("search"); removeClass(search, "hidden"); search.innerHTML = output; - var tds = search.getElementsByTagName("td"); - var td_width = 0; + let tds = search.getElementsByTagName("td"); + let td_width = 0; if (tds.length > 0) { td_width = tds[0].offsetWidth; } - var width = search.offsetWidth - 40 - td_width; + let width = search.offsetWidth - 40 - td_width; onEachLazy(search.getElementsByClassName("desc"), function(e) { e.style.width = width + "px"; }); initSearchNav(); - var elems = document.getElementById("titles").childNodes; + let elems = document.getElementById("titles").childNodes; elems[0].onclick = function() { printTab(0); }; elems[1].onclick = function() { printTab(1); }; elems[2].onclick = function() { printTab(2); }; @@ -1410,9 +1410,9 @@ if (!DOMTokenList.prototype.remove) { function execSearch(query, searchWords, filterCrates) { function getSmallest(arrays, positions, notDuplicates) { - var start = null; + let start = null; - for (var it = 0; it < positions.length; ++it) { + for (let it = 0; it < positions.length; ++it) { if (arrays[it].length > positions[it] && (start === null || start > arrays[it][positions[it]].lev) && !notDuplicates[arrays[it][positions[it]].fullPath]) { @@ -1423,15 +1423,15 @@ if (!DOMTokenList.prototype.remove) { } function mergeArrays(arrays) { - var ret = []; - var positions = []; - var notDuplicates = {}; + let ret = []; + let positions = []; + let notDuplicates = {}; - for (var x = 0; x < arrays.length; ++x) { + for (let x = 0; x < arrays.length; ++x) { positions.push(0); } while (ret.length < MAX_RESULTS) { - var smallest = getSmallest(arrays, positions, notDuplicates); + let smallest = getSmallest(arrays, positions, notDuplicates); if (smallest === null) { break; @@ -1449,17 +1449,17 @@ if (!DOMTokenList.prototype.remove) { return ret; } - var queries = query.raw.split(","); - var results = { + let queries = query.raw.split(","); + let results = { "in_args": [], "returned": [], "others": [], }; - for (var i = 0; i < queries.length; ++i) { + for (let i = 0; i < queries.length; ++i) { query = queries[i].trim(); if (query.length !== 0) { - var tmp = execQuery(getQuery(query), searchWords, filterCrates); + let tmp = execQuery(getQuery(query), searchWords, filterCrates); results.in_args.push(tmp.in_args); results.returned.push(tmp.returned); @@ -1482,7 +1482,7 @@ if (!DOMTokenList.prototype.remove) { } function getFilterCrates() { - var elem = document.getElementById("crate-search"); + let elem = document.getElementById("crate-search"); if (elem && elem.value !== "All crates" && rawSearchIndex.hasOwnProperty(elem.value)) { return elem.value; @@ -1491,8 +1491,8 @@ if (!DOMTokenList.prototype.remove) { } function search(e, forced) { - var params = getQueryStringParams(); - var query = getQuery(search_input.value.trim()); + let params = getQueryStringParams(); + let query = getQuery(search_input.value.trim()); if (e) { e.preventDefault(); @@ -1521,16 +1521,16 @@ if (!DOMTokenList.prototype.remove) { } } - var filterCrates = getFilterCrates(); + let filterCrates = getFilterCrates(); showResults(execSearch(query, index, filterCrates), filterCrates); } function buildIndex(rawSearchIndex) { searchIndex = []; - var searchWords = []; - var i; + let searchWords = []; + let i; - for (var crate in rawSearchIndex) { + for (let crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } searchWords.push(crate); @@ -1549,13 +1549,13 @@ if (!DOMTokenList.prototype.remove) { // (String) description, // (Number | null) the parent path index to `paths`] // (Object | null) the type of the function (if any) - var items = rawSearchIndex[crate].items; + let items = rawSearchIndex[crate].items; // an array of [(Number) item type, // (String) name] - var paths = rawSearchIndex[crate].paths; + let paths = rawSearchIndex[crate].paths; // convert `paths` into an object form - var len = paths.length; + let len = paths.length; for (i = 0; i < len; ++i) { paths[i] = {ty: paths[i][0], name: paths[i][1]}; } @@ -1568,15 +1568,15 @@ if (!DOMTokenList.prototype.remove) { // all other search operations have access to this cached data for // faster analysis operations len = items.length; - var lastPath = ""; + let lastPath = ""; for (i = 0; i < len; ++i) { - var rawRow = items[i]; - var row = {crate: crate, ty: rawRow[0], name: rawRow[1], + let rawRow = items[i]; + let row = {crate: crate, ty: rawRow[0], name: rawRow[1], path: rawRow[2] || lastPath, desc: rawRow[3], parent: paths[rawRow[4]], type: rawRow[5]}; searchIndex.push(row); if (typeof row.name === "string") { - var word = row.name.toLowerCase(); + let word = row.name.toLowerCase(); searchWords.push(word); } else { searchWords.push(""); @@ -1588,8 +1588,8 @@ if (!DOMTokenList.prototype.remove) { } function startSearch() { - var searchTimeout; - var callback = function() { + let searchTimeout; + let callback = function() { clearTimeout(searchTimeout); if (search_input.value.length === 0) { if (browserSupportsHistoryApi()) { @@ -1598,7 +1598,7 @@ if (!DOMTokenList.prototype.remove) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + let search_c = document.getElementById("search"); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -1613,7 +1613,7 @@ if (!DOMTokenList.prototype.remove) { clearTimeout(searchTimeout); search(); }; - search_input.onchange = function(e) { + search_input.onchange = function() { // Do NOT e.preventDefault() here. It will prevent pasting. clearTimeout(searchTimeout); // zero-timeout necessary here because at the time of event handler execution the @@ -1623,7 +1623,7 @@ if (!DOMTokenList.prototype.remove) { }; search_input.onpaste = search_input.onchange; - var selectCrate = document.getElementById('crate-search'); + let selectCrate = document.getElementById('crate-search'); if (selectCrate) { selectCrate.onchange = function() { search(undefined, true); @@ -1634,17 +1634,17 @@ if (!DOMTokenList.prototype.remove) { // history. if (browserSupportsHistoryApi()) { // Store the previous so we can revert back to it later. - var previousTitle = document.title; + let previousTitle = document.title; - window.onpopstate = function(e) { - var params = getQueryStringParams(); + window.onpopstate = function() { + let params = getQueryStringParams(); // When browsing back from search results the main page // visibility must be reset. if (!params.search) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + let search_c = document.getElementById("search"); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -1681,34 +1681,34 @@ if (!DOMTokenList.prototype.remove) { // Draw a convenient sidebar of known crates if we have a listing if (rootPath === "../" || rootPath === "./") { - var sidebar = document.getElementsByClassName("sidebar-elems")[0]; + let sidebar = document.getElementsByClassName("sidebar-elems")[0]; if (sidebar) { - var div = document.createElement("div"); + let div = document.createElement("div"); div.className = "block crate"; div.innerHTML = "<h3>Crates</h3>"; - var ul = document.createElement("ul"); + let ul = document.createElement("ul"); div.appendChild(ul); - var crates = []; - for (var crate in rawSearchIndex) { + let crates = []; + for (let crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } crates.push(crate); } crates.sort(); - for (var i = 0; i < crates.length; ++i) { - var klass = "crate"; + for (let i = 0; i < crates.length; ++i) { + let klass = "crate"; if (rootPath !== "./" && crates[i] === window.currentCrate) { klass += " current"; } - var link = document.createElement("a"); + let link = document.createElement("a"); link.href = rootPath + crates[i] + "/index.html"; link.title = rawSearchIndex[crates[i]].doc; link.className = klass; link.textContent = crates[i]; - var li = document.createElement("li"); + let li = document.createElement("li"); li.appendChild(link); ul.appendChild(li); } @@ -1721,44 +1721,44 @@ if (!DOMTokenList.prototype.remove) { // delayed sidebar rendering. function initSidebarItems(items) { - var sidebar = document.getElementsByClassName("sidebar-elems")[0]; - var current = window.sidebarCurrent; + let sidebar = document.getElementsByClassName("sidebar-elems")[0]; + let current = window.sidebarCurrent; function block(shortty, longty) { - var filtered = items[shortty]; + let filtered = items[shortty]; if (!filtered) { return; } - var div = document.createElement("div"); + let div = document.createElement("div"); div.className = "block " + shortty; - var h3 = document.createElement("h3"); + let h3 = document.createElement("h3"); h3.textContent = longty; div.appendChild(h3); - var ul = document.createElement("ul"); + let ul = document.createElement("ul"); - var length = filtered.length; - for (var i = 0; i < length; ++i) { - var item = filtered[i]; - var name = item[0]; - var desc = item[1]; // can be null + let length = filtered.length; + for (let i = 0; i < length; ++i) { + let item = filtered[i]; + let name = item[0]; + let desc = item[1]; // can be null - var klass = shortty; + let klass = shortty; if (name === current.name && shortty === current.ty) { klass += " current"; } - var path; + let path; if (shortty === "mod") { path = name + "/index.html"; } else { path = shortty + "." + name + ".html"; } - var link = document.createElement("a"); + let link = document.createElement("a"); link.href = current.relpath + path; link.title = desc; link.className = klass; link.textContent = name; - var li = document.createElement("li"); + let li = document.createElement("li"); li.appendChild(link); ul.appendChild(li); } @@ -1786,25 +1786,25 @@ if (!DOMTokenList.prototype.remove) { window.initSidebarItems = initSidebarItems; window.register_implementors = function(imp) { - var implementors = document.getElementById("implementors-list"); - var synthetic_implementors = document.getElementById("synthetic-implementors-list"); + let implementors = document.getElementById("implementors-list"); + let synthetic_implementors = document.getElementById("synthetic-implementors-list"); - var libs = Object.getOwnPropertyNames(imp); - var llength = libs.length; - for (var i = 0; i < llength; ++i) { + let libs = Object.getOwnPropertyNames(imp); + let llength = libs.length; + for (let i = 0; i < llength; ++i) { if (libs[i] === currentCrate) { continue; } - var structs = imp[libs[i]]; + let structs = imp[libs[i]]; - var slength = structs.length; + let slength = structs.length; struct_loop: - for (var j = 0; j < slength; ++j) { - var struct = structs[j]; + for (let j = 0; j < slength; ++j) { + let struct = structs[j]; - var list = struct.synthetic ? synthetic_implementors : implementors; + let list = struct.synthetic ? synthetic_implementors : implementors; if (struct.synthetic) { - var stlength = struct.types.length; - for (var k = 0; k < stlength; k++) { + let stlength = struct.types.length; + for (let k = 0; k < stlength; k++) { if (window.inlined_types.has(struct.types[k])) { continue struct_loop; } @@ -1812,18 +1812,18 @@ if (!DOMTokenList.prototype.remove) { } } - var code = document.createElement("code"); + let code = document.createElement("code"); code.innerHTML = struct.text; - var x = code.getElementsByTagName("a"); - var xlength = x.length; - for (var it = 0; it < xlength; it++) { - var href = x[it].getAttribute("href"); + let x = code.getElementsByTagName("a"); + let xlength = x.length; + for (let it = 0; it < xlength; it++) { + let href = x[it].getAttribute("href"); if (href && href.indexOf("http") !== 0) { x[it].setAttribute("href", rootPath + href); } } - var display = document.createElement("h3"); + let display = document.createElement("h3"); addClass(display, "impl"); display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" + "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" + @@ -1848,9 +1848,9 @@ if (!DOMTokenList.prototype.remove) { function onEveryMatchingChild(elem, className, func) { if (elem && className && func) { - var length = elem.childNodes.length; - var nodes = elem.childNodes; - for (var i = 0; i < length; ++i) { + let length = elem.childNodes.length; + let nodes = elem.childNodes; + for (let i = 0; i < length; ++i) { if (hasClass(nodes[i], className)) { func(nodes[i]); } else { @@ -1861,7 +1861,7 @@ if (!DOMTokenList.prototype.remove) { } function toggleAllDocs(pageId, fromAutoCollapse) { - var innerToggle = document.getElementById("toggle-all-docs"); + let innerToggle = document.getElementById("toggle-all-docs"); if (!innerToggle) { return; } @@ -1914,7 +1914,7 @@ if (!DOMTokenList.prototype.remove) { function implHider(addOrRemove) { return function(n) { - var is_method = hasClass(n, "method"); + let is_method = hasClass(n, "method"); if (is_method || hasClass(n, "type")) { if (is_method === true) { if (addOrRemove) { @@ -1923,7 +1923,7 @@ if (!DOMTokenList.prototype.remove) { removeClass(n, "hidden-by-impl-hider"); } } - var ns = n.nextElementSibling; + let ns = n.nextElementSibling; while (true) { if (ns && ( hasClass(ns, "docblock") || @@ -1942,8 +1942,8 @@ if (!DOMTokenList.prototype.remove) { }; } - var relatedDoc; - var action = mode; + let relatedDoc; + let action = mode; if (hasClass(toggle.parentNode, "impl") === false) { relatedDoc = toggle.parentNode.nextElementSibling; if (hasClass(relatedDoc, "stability")) { @@ -1970,9 +1970,9 @@ if (!DOMTokenList.prototype.remove) { } else { // we are collapsing the impl block - var parentElem = toggle.parentNode; + let parentElem = toggle.parentNode; relatedDoc = parentElem; - var docblock = relatedDoc.nextElementSibling; + let docblock = relatedDoc.nextElementSibling; while (hasClass(relatedDoc, "impl-items") === false) { relatedDoc = relatedDoc.nextElementSibling; @@ -2011,7 +2011,7 @@ if (!DOMTokenList.prototype.remove) { function collapser(e, collapse) { // inherent impl ids are like "impl" or impl-<number>'. // they will never be hidden by default. - var n = e.parentElement; + let n = e.parentElement; if (n.id.match(/^impl(?:-\d+)?$/) === null) { // Automatically minimize all non-inherent impls if (collapse || hasClass(n, "impl")) { @@ -2024,7 +2024,7 @@ if (!DOMTokenList.prototype.remove) { if (collapse) { toggleAllDocs(pageId, true); } else if (getCurrentValue("rustdoc-trait-implementations") !== "false") { - var impl_list = document.getElementById("implementations-list"); + let impl_list = document.getElementById("implementations-list"); if (impl_list !== null) { onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) { @@ -2034,7 +2034,7 @@ if (!DOMTokenList.prototype.remove) { } } - var toggles = document.getElementById("toggle-all-docs"); + let toggles = document.getElementById("toggle-all-docs"); if (toggles) { toggles.onclick = toggleAllDocs; } @@ -2044,7 +2044,7 @@ if (!DOMTokenList.prototype.remove) { } function createSimpleToggle(sectionIsCollapsed) { - var toggle = document.createElement("a"); + let toggle = document.createElement("a"); toggle.href = "javascript:void(0)"; toggle.className = "collapse-toggle"; toggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(sectionIsCollapsed) + @@ -2052,10 +2052,10 @@ if (!DOMTokenList.prototype.remove) { return toggle; } - var toggle = createSimpleToggle(false); + let toggle = createSimpleToggle(false); - var func = function(e) { - var next = e.nextElementSibling; + let func = function(e) { + let next = e.nextElementSibling; if (!next) { return; } @@ -2066,8 +2066,8 @@ if (!DOMTokenList.prototype.remove) { } }; - var funcImpl = function(e) { - var next = e.nextElementSibling; + let funcImpl = function(e) { + let next = e.nextElementSibling; if (next && hasClass(next, "docblock")) { next = next.nextElementSibling; } @@ -2082,7 +2082,7 @@ if (!DOMTokenList.prototype.remove) { onEachLazy(document.getElementsByClassName("method"), func); onEachLazy(document.getElementsByClassName("associatedconstant"), func); onEachLazy(document.getElementsByClassName("impl"), funcImpl); - var impl_call = function() {}; + let impl_call = function() {}; if (getCurrentValue("rustdoc-method-docs") !== "false") { impl_call = function(e, newToggle, pageId) { if (e.id.match(/^impl(?:-\d+)?$/) === null) { @@ -2093,8 +2093,8 @@ if (!DOMTokenList.prototype.remove) { } }; } - var pageId = getPageId(); - var newToggle = document.createElement("a"); + let pageId = getPageId(); + let newToggle = document.createElement("a"); newToggle.href = "javascript:void(0)"; newToggle.className = "collapse-toggle hidden-default collapsed"; newToggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) + @@ -2124,11 +2124,11 @@ if (!DOMTokenList.prototype.remove) { } onEachLazy(document.getElementsByClassName("impl-items"), function(e) { onEachLazy(e.getElementsByClassName("associatedconstant"), func); - var hiddenElems = e.getElementsByClassName("hidden"); - var needToggle = false; + let hiddenElems = e.getElementsByClassName("hidden"); + let needToggle = false; - var hlength = hiddenElems.length; - for (var i = 0; i < hlength; ++i) { + let hlength = hiddenElems.length; + for (let i = 0; i < hlength; ++i) { if (hasClass(hiddenElems[i], "content") === false && hasClass(hiddenElems[i], "docblock") === false) { needToggle = true; @@ -2136,7 +2136,7 @@ if (!DOMTokenList.prototype.remove) { } } if (needToggle === true) { - var inner_toggle = newToggle.cloneNode(true); + let inner_toggle = newToggle.cloneNode(true); inner_toggle.onclick = toggleClicked; e.insertBefore(inner_toggle, e.firstChild); impl_call(e, inner_toggle, pageId); @@ -2144,7 +2144,7 @@ if (!DOMTokenList.prototype.remove) { }); function createToggle(otherMessage, fontSize, extraClass, show) { - var span = document.createElement("span"); + let span = document.createElement("span"); span.className = "toggle-label"; if (show) { span.style.display = "none"; @@ -2159,14 +2159,14 @@ if (!DOMTokenList.prototype.remove) { span.style.fontSize = fontSize; } - var mainToggle = toggle.cloneNode(true); + let mainToggle = toggle.cloneNode(true); mainToggle.appendChild(span); - var wrapper = document.createElement("div"); + let wrapper = document.createElement("div"); wrapper.className = "toggle-wrapper"; if (!show) { addClass(wrapper, "collapsed"); - var inner = mainToggle.getElementsByClassName("inner"); + let inner = mainToggle.getElementsByClassName("inner"); if (inner && inner.length > 0) { inner[0].innerHTML = "+"; } @@ -2178,13 +2178,13 @@ if (!DOMTokenList.prototype.remove) { return wrapper; } - var showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; + let showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; function buildToggleWrapper(e) { if (hasClass(e, "autohide")) { - var wrap = e.previousElementSibling; + let wrap = e.previousElementSibling; if (wrap && hasClass(wrap, "toggle-wrapper")) { - var inner_toggle = wrap.childNodes[0]; - var extra = e.childNodes[0].tagName === "H3"; + let inner_toggle = wrap.childNodes[0]; + let extra = e.childNodes[0].tagName === "H3"; e.style.display = "none"; addClass(wrap, "collapsed"); @@ -2200,9 +2200,9 @@ if (!DOMTokenList.prototype.remove) { } } if (e.parentNode.id === "main") { - var otherMessage = ""; - var fontSize; - var extraClass; + let otherMessage = ""; + let fontSize; + let extraClass; if (hasClass(e, "type-decl")) { fontSize = "20px"; @@ -2246,7 +2246,7 @@ if (!DOMTokenList.prototype.remove) { if (nb === 0 || nb === 1 || nb === 2) { currentTab = nb; } - var nb_copy = nb; + let nb_copy = nb; onEachLazy(document.getElementById("titles").childNodes, function(elem) { if (nb_copy === 0) { addClass(elem, "selected"); @@ -2266,41 +2266,41 @@ if (!DOMTokenList.prototype.remove) { } function createToggleWrapper(tog) { - var span = document.createElement("span"); + let span = document.createElement("span"); span.className = "toggle-label"; span.style.display = "none"; span.innerHTML = " Expand attributes"; tog.appendChild(span); - var wrapper = document.createElement("div"); + let wrapper = document.createElement("div"); wrapper.className = "toggle-wrapper toggle-attributes"; wrapper.appendChild(tog); return wrapper; } // To avoid checking on "rustdoc-item-attributes" value on every loop... - var itemAttributesFunc = function() {}; + let itemAttributesFunc = function() {}; if (getCurrentValue("rustdoc-item-attributes") !== "false") { itemAttributesFunc = function(x) { collapseDocs(x.previousSibling.childNodes[0], "toggle"); }; } - var attributesToggle = createToggleWrapper(createSimpleToggle(false)); + let attributesToggle = createToggleWrapper(createSimpleToggle(false)); onEachLazy(main.getElementsByClassName("attributes"), function(i_e) { i_e.parentNode.insertBefore(attributesToggle.cloneNode(true), i_e); itemAttributesFunc(i_e); }); // To avoid checking on "rustdoc-line-numbers" value on every loop... - var lineNumbersFunc = function() {}; + let lineNumbersFunc = function() {}; if (getCurrentValue("rustdoc-line-numbers") === "true") { lineNumbersFunc = function(x) { - var count = x.textContent.split("\n").length; - var elems = []; - for (var i = 0; i < count; ++i) { + let count = x.textContent.split("\n").length; + let elems = []; + for (let i = 0; i < count; ++i) { elems.push(i + 1); } - var node = document.createElement("pre"); + let node = document.createElement("pre"); addClass(node, "line-number"); node.innerHTML = elems.join("\n"); x.parentNode.insertBefore(node, x); @@ -2308,17 +2308,17 @@ if (!DOMTokenList.prototype.remove) { } onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) { if (hasClass(e, "compile_fail")) { - e.addEventListener("mouseover", function(event) { + e.addEventListener("mouseover", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00"; }); - e.addEventListener("mouseout", function(event) { + e.addEventListener("mouseout", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = ""; }); } else if (hasClass(e, "ignore")) { - e.addEventListener("mouseover", function(event) { + e.addEventListener("mouseover", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200"; }); - e.addEventListener("mouseout", function(event) { + e.addEventListener("mouseout", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = ""; }); } @@ -2326,7 +2326,7 @@ if (!DOMTokenList.prototype.remove) { }); function showModal(content) { - var modal = document.createElement("div"); + let modal = document.createElement("div"); modal.id = "important"; addClass(modal, "modal"); modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" + @@ -2338,7 +2338,7 @@ if (!DOMTokenList.prototype.remove) { } function hideModal() { - var modal = document.getElementById("important"); + let modal = document.getElementById("important"); if (modal) { modal.parentNode.removeChild(modal); } @@ -2368,18 +2368,18 @@ if (!DOMTokenList.prototype.remove) { }; } - var params = getQueryStringParams(); + let params = getQueryStringParams(); if (params && params.search) { addClass(main, "hidden"); - var search = document.getElementById("search"); + let search = document.getElementById("search"); removeClass(search, "hidden"); search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>"; } - var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; + let sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; if (sidebar_menu) { sidebar_menu.onclick = function() { - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; if (hasClass(sidebar, "mobile") === true) { hideSidebar(); } else { @@ -2410,22 +2410,22 @@ if (!DOMTokenList.prototype.remove) { } function addSearchOptions(crates) { - var elem = document.getElementById('crate-search'); + let elem = document.getElementById('crate-search'); if (!elem) { return; } - var crates_text = []; + let crates_text = []; if (crates.length > 1) { - for (var crate in crates) { + for (let crate in crates) { if (crates.hasOwnProperty(crate)) { crates_text.push(crate); } } } crates_text.sort(function(a, b) { - var lower_a = a.toLowerCase(); - var lower_b = b.toLowerCase(); + let lower_a = a.toLowerCase(); + let lower_b = b.toLowerCase(); if (lower_a < lower_b) { return -1; @@ -2434,8 +2434,8 @@ if (!DOMTokenList.prototype.remove) { } return 0; }); - for (var i = 0; i < crates_text.length; ++i) { - var option = document.createElement("option"); + for (let i = 0; i < crates_text.length; ++i) { + let option = document.createElement("option"); option.value = crates_text[i]; option.innerText = crates_text[i]; elem.appendChild(option); diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js index 427a74c0c87fa..e985c4f8ba24a 100644 --- a/src/librustdoc/html/static/settings.js +++ b/src/librustdoc/html/static/settings.js @@ -11,14 +11,14 @@ } function setEvents() { - var elems = document.getElementsByClassName("slider"); + let elems = document.getElementsByClassName("slider"); if (!elems || elems.length === 0) { return; } - for (var i = 0; i < elems.length; ++i) { - var toggle = elems[i].previousElementSibling; - var settingId = toggle.id; - var settingValue = getSettingValue(settingId); + for (let i = 0; i < elems.length; ++i) { + let toggle = elems[i].previousElementSibling; + let settingId = toggle.id; + let settingValue = getSettingValue(settingId); if (settingValue !== null) { toggle.checked = settingValue === "true"; } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 6ef70fb7d3502..2780cadb7a6d8 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -8,15 +8,15 @@ /* global addClass, getCurrentValue, hasClass, removeClass, updateLocalStorage */ function getCurrentFilePath() { - var parts = window.location.pathname.split("/"); - var rootPathParts = window.rootPath.split("/"); + let parts = window.location.pathname.split("/"); + let rootPathParts = window.rootPath.split("/"); - for (var i = 0; i < rootPathParts.length; ++i) { + for (let i = 0; i < rootPathParts.length; ++i) { if (rootPathParts[i] === "..") { parts.pop(); } } - var file = window.location.pathname.substring(parts.join("/").length); + let file = window.location.pathname.substring(parts.join("/").length); if (file.startsWith("/")) { file = file.substring(1); } @@ -24,7 +24,7 @@ function getCurrentFilePath() { } function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { - var name = document.createElement("div"); + let name = document.createElement("div"); name.className = "name"; fullPath += elem["name"] + "/"; @@ -38,11 +38,11 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { }; name.innerText = elem["name"]; - var children = document.createElement("div"); + let children = document.createElement("div"); children.className = "children"; - var folders = document.createElement("div"); + let folders = document.createElement("div"); folders.className = "folders"; - for (var i = 0; i < elem.dirs.length; ++i) { + for (let i = 0; i < elem.dirs.length; ++i) { if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile, hasFoundFile) === true) { addClass(name, "expand"); @@ -51,10 +51,10 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { } children.appendChild(folders); - var files = document.createElement("div"); + let files = document.createElement("div"); files.className = "files"; - for (i = 0; i < elem.files.length; ++i) { - var file = document.createElement("a"); + for (let i = 0; i < elem.files.length; ++i) { + let file = document.createElement("a"); file.innerText = elem.files[i]; file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html"; if (hasFoundFile === false && @@ -73,8 +73,8 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { } function toggleSidebar() { - var sidebar = document.getElementById("source-sidebar"); - var child = this.children[0].children[0]; + let sidebar = document.getElementById("source-sidebar"); + let child = this.children[0].children[0]; if (child.innerText === ">") { sidebar.style.left = ""; this.style.left = ""; @@ -89,14 +89,14 @@ function toggleSidebar() { } function createSidebarToggle() { - var sidebarToggle = document.createElement("div"); + let sidebarToggle = document.createElement("div"); sidebarToggle.id = "sidebar-toggle"; sidebarToggle.onclick = toggleSidebar; - var inner1 = document.createElement("div"); + let inner1 = document.createElement("div"); inner1.style.position = "relative"; - var inner2 = document.createElement("div"); + let inner2 = document.createElement("div"); inner2.style.marginTop = "-2px"; if (getCurrentValue("rustdoc-source-sidebar-show") === "true") { inner2.innerText = "<"; @@ -114,21 +114,21 @@ function createSourceSidebar() { if (window.rootPath.endsWith("/") === false) { window.rootPath += "/"; } - var main = document.getElementById("main"); + let main = document.getElementById("main"); - var sidebarToggle = createSidebarToggle(); + let sidebarToggle = createSidebarToggle(); main.insertBefore(sidebarToggle, main.firstChild); - var sidebar = document.createElement("div"); + let sidebar = document.createElement("div"); sidebar.id = "source-sidebar"; if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") { sidebar.style.left = "-300px"; } - var currentFile = getCurrentFilePath(); - var hasFoundFile = false; + let currentFile = getCurrentFilePath(); + let hasFoundFile = false; - var title = document.createElement("div"); + let title = document.createElement("div"); title.className = "title"; title.innerText = "Files"; sidebar.appendChild(title); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 27b6f40d797f3..25c11c655285a 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -33,15 +33,15 @@ function isHidden(elem) { function onEach(arr, func, reversed) { if (arr && arr.length > 0 && func) { - var length = arr.length; + let length = arr.length; if (reversed !== true) { - for (var i = 0; i < length; ++i) { + for (let i = 0; i < length; ++i) { if (func(arr[i]) === true) { return true; } } } else { - for (var i = length - 1; i >= 0; --i) { + for (let i = length - 1; i >= 0; --i) { if (func(arr[i]) === true) { return true; } @@ -92,15 +92,15 @@ function getCurrentValue(name) { } function switchTheme(styleElem, mainStyleElem, newTheme) { - var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; - var fullNewTheme = newTheme + resourcesSuffix + ".css"; - var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); + let fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; + let fullNewTheme = newTheme + resourcesSuffix + ".css"; + let newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); if (styleElem.href === newHref) { return; } - var found = false; + let found = false; if (savedHref.length === 0) { onEachLazy(document.getElementsByTagName("link"), function(el) { savedHref.push(el.href); From 8c304d39d4679335f362e98a0158c11edffc22d3 Mon Sep 17 00:00:00 2001 From: John Heitmann <jheitmann@gmail.com> Date: Wed, 2 Jan 2019 10:42:43 -0800 Subject: [PATCH 003/124] Clean up eslint pragma formatting --- src/librustdoc/html/static/storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 25c11c655285a..00741619d2dd7 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -2,7 +2,7 @@ /* global resourcesSuffix */ // eslint doesn't understand the functions here are used elsewhere -/*eslint no-unused-vars: "off"*/ +/* eslint no-unused-vars: "off" */ var currentTheme = document.getElementById("themeStyle"); var mainTheme = document.getElementById("mainThemeStyle"); From aa429bd1427fbb6a214a64e1ce9b3f03a5b902b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= <faern@faern.net> Date: Fri, 14 Dec 2018 19:24:19 +0100 Subject: [PATCH 004/124] Use checked_add for adding time in recv_timeout --- src/libstd/sync/mpsc/mod.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index ecdf7e5668cd2..446c164965d6f 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1311,12 +1311,13 @@ impl<T> Receiver<T> { // Do an optimistic try_recv to avoid the performance impact of // Instant::now() in the full-channel case. match self.try_recv() { - Ok(result) - => Ok(result), - Err(TryRecvError::Disconnected) - => Err(RecvTimeoutError::Disconnected), - Err(TryRecvError::Empty) - => self.recv_deadline(Instant::now() + timeout) + Ok(result) => Ok(result), + Err(TryRecvError::Disconnected) => Err(RecvTimeoutError::Disconnected), + Err(TryRecvError::Empty) => match Instant::now().checked_add(timeout) { + Some(deadline) => self.recv_deadline(deadline), + // So far in the future that it's practically the same as waiting indefinitely. + None => self.recv().map_err(RecvTimeoutError::from), + }, } } @@ -2301,6 +2302,17 @@ mod tests { assert_eq!(recv_count, stress); } + #[test] + fn very_long_recv_timeout_wont_panic() { + let (tx, rx) = channel::<()>(); + let join_handle = thread::spawn(move || { + rx.recv_timeout(Duration::from_secs(u64::max_value())) + }); + thread::sleep(Duration::from_secs(1)); + assert!(tx.send(()).is_ok()); + assert_eq!(join_handle.join().unwrap(), Ok(())); + } + #[test] fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context From e1f7cd8a866b960a5409932a31a3e57e59b9ac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= <faern@faern.net> Date: Fri, 14 Dec 2018 20:07:04 +0100 Subject: [PATCH 005/124] Add documentation about panicking Add<Duration> impls --- src/libstd/time.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index ffe604cd33bd8..eb67b718dbd3d 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -220,6 +220,12 @@ impl Instant { impl Add<Duration> for Instant { type Output = Instant; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { self.checked_add(other) .expect("overflow when adding duration to instant") @@ -387,6 +393,12 @@ impl SystemTime { impl Add<Duration> for SystemTime { type Output = SystemTime; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { self.checked_add(dur) .expect("overflow when adding duration to instant") From 2f9d3c70c820fa40e0322c917e3df5963c52d3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Wed, 5 Dec 2018 23:28:38 +0100 Subject: [PATCH 006/124] Uninline some debugging code and use unlikely! macro --- src/librustc/ty/query/plumbing.rs | 57 ++++++++++++++++++------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 5d23ee0994a06..6887f480f72e0 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -503,37 +503,48 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If -Zincremental-verify-ich is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. - if self.sess.opts.debugging_opts.incremental_verify_ich { - use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; - use ich::Fingerprint; + if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) { + self.incremental_verify_ich::<Q>(&result, dep_node, dep_node_index); + } - assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == - self.dep_graph.prev_fingerprint_of(dep_node), - "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { + self.dep_graph.mark_loaded_from_cache(dep_node_index, true); + } - debug!("BEGIN verify_ich({:?})", dep_node); - let mut hcx = self.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); + job.complete(&result, dep_node_index); - result.hash_stable(&mut hcx, &mut hasher); + Ok(result) + } - let new_hash: Fingerprint = hasher.finish(); - debug!("END verify_ich({:?})", dep_node); + #[inline(never)] + #[cold] + fn incremental_verify_ich<Q: QueryDescription<'gcx>>( + self, + result: &Q::Value, + dep_node: &DepNode, + dep_node_index: DepNodeIndex, + ) { + use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; + use ich::Fingerprint; - let old_hash = self.dep_graph.fingerprint_of(dep_node_index); + assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == + self.dep_graph.prev_fingerprint_of(dep_node), + "Fingerprint for green query instance not loaded \ + from cache: {:?}", dep_node); - assert!(new_hash == old_hash, "Found unstable fingerprints \ - for {:?}", dep_node); - } + debug!("BEGIN verify_ich({:?})", dep_node); + let mut hcx = self.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); - if self.sess.opts.debugging_opts.query_dep_graph { - self.dep_graph.mark_loaded_from_cache(dep_node_index, true); - } + result.hash_stable(&mut hcx, &mut hasher); - job.complete(&result, dep_node_index); + let new_hash: Fingerprint = hasher.finish(); + debug!("END verify_ich({:?})", dep_node); - Ok(result) + let old_hash = self.dep_graph.fingerprint_of(dep_node_index); + + assert!(new_hash == old_hash, "Found unstable fingerprints \ + for {:?}", dep_node); } fn force_query_with_job<Q: QueryDescription<'gcx>>( @@ -578,7 +589,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ((result, dep_node_index), diagnostics) = res; - if self.sess.opts.debugging_opts.query_dep_graph { + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { self.dep_graph.mark_loaded_from_cache(dep_node_index, false); } From 44ba1e9f1ca0d388d06a13278f0be39e274b6575 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Sat, 1 Dec 2018 02:47:08 +0000 Subject: [PATCH 007/124] Store `Ident` rather than just `Name` in HIR types `Item` and `ForeignItem`. --- src/libproc_macro/bridge/rpc.rs | 2 +- src/librustc/hir/intravisit.rs | 13 ++--- src/librustc/hir/lowering.rs | 54 +++++++++---------- src/librustc/hir/map/blocks.rs | 2 +- src/librustc/hir/map/mod.rs | 16 +++--- src/librustc/hir/mod.rs | 6 +-- src/librustc/hir/print.rs | 37 ++++++------- src/librustc/ich/impls_hir.rs | 8 +-- src/librustc/middle/dead.rs | 6 +-- src/librustc/middle/entry.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/layout.rs | 10 ++-- src/librustc/ty/mod.rs | 12 ++--- .../debuginfo/metadata.rs | 12 ++--- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/nonstandard_style.rs | 8 +-- src/librustc_lint/types.rs | 2 +- src/librustc_metadata/decoder.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 2 +- src/librustc_mir/hair/pattern/mod.rs | 2 +- src/librustc_mir/interpret/validity.rs | 2 +- src/librustc_resolve/macros.rs | 2 +- src/librustc_typeck/astconv.rs | 4 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 10 ++-- src/librustc_typeck/check_unused.rs | 8 +-- src/librustc_typeck/collect.rs | 19 +++---- src/librustdoc/clean/mod.rs | 15 ++++-- .../passes/collect_intra_doc_links.rs | 2 +- src/librustdoc/test.rs | 6 +-- src/librustdoc/visit_ast.rs | 40 +++++++------- .../auxiliary/lint_group_plugin_test.rs | 51 ++++++++++++++++++ .../auxiliary/lint_group_plugin_test.rs | 4 +- src/test/ui-fulldeps/lint-group-plugin.rs | 1 + src/test/ui-fulldeps/lint-group-plugin.stderr | 4 +- 38 files changed, 221 insertions(+), 157 deletions(-) create mode 100644 src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs diff --git a/src/libproc_macro/bridge/rpc.rs b/src/libproc_macro/bridge/rpc.rs index ed5136462cf3d..6685aa1acac39 100644 --- a/src/libproc_macro/bridge/rpc.rs +++ b/src/libproc_macro/bridge/rpc.rs @@ -1,4 +1,4 @@ -//! Serialization for client<->server communication. +//! Serialization for client-server communication. use std::any::Any; use std::char; diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2f0a95445a886..d4f891c874a40 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -454,7 +454,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_vis(&item.vis); - visitor.visit_name(item.span, item.name); + visitor.visit_ident(item.ident); match item.node { ItemKind::ExternCrate(orig_name) => { visitor.visit_id(item.id); @@ -472,7 +472,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_nested_body(body); } ItemKind::Fn(ref declaration, header, ref generics, body_id) => { - visitor.visit_fn(FnKind::ItemFn(item.name, + visitor.visit_fn(FnKind::ItemFn(item.ident.name, generics, header, &item.vis, @@ -528,7 +528,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { ItemKind::Union(ref struct_definition, ref generics) => { visitor.visit_generics(generics); visitor.visit_id(item.id); - visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); + visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.id, + item.span); } ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => { visitor.visit_id(item.id); @@ -569,9 +570,9 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant, generics: &'v Generics, parent_item_id: NodeId) { - visitor.visit_name(variant.span, variant.node.name); + visitor.visit_ident(variant.node.ident); visitor.visit_variant_data(&variant.node.data, - variant.node.name, + variant.node.ident.name, generics, parent_item_id, variant.span); @@ -720,7 +721,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) { visitor.visit_id(foreign_item.id); visitor.visit_vis(&foreign_item.vis); - visitor.visit_name(foreign_item.span, foreign_item.name); + visitor.visit_ident(foreign_item.ident); match foreign_item.node { ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 32514caff876c..359bd37488241 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1360,7 +1360,7 @@ impl<'a> LoweringContext<'a> { let exist_ty_item = hir::Item { id: exist_ty_id.node_id, hir_id: exist_ty_id.hir_id, - name: keywords::Invalid.name(), + ident: keywords::Invalid.ident(), attrs: Default::default(), node: exist_ty_item_kind, vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited), @@ -1563,7 +1563,7 @@ impl<'a> LoweringContext<'a> { fn lower_variant(&mut self, v: &Variant) -> hir::Variant { Spanned { node: hir::VariantKind { - name: v.node.ident.name, + ident: v.node.ident, attrs: self.lower_attrs(&v.node.attrs), data: self.lower_variant_data(&v.node.data), disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), @@ -2737,7 +2737,7 @@ impl<'a> LoweringContext<'a> { fn lower_item_kind( &mut self, id: NodeId, - name: &mut Name, + ident: &mut Ident, attrs: &hir::HirVec<Attribute>, vis: &mut hir::Visibility, i: &ItemKind, @@ -2751,7 +2751,7 @@ impl<'a> LoweringContext<'a> { span: use_tree.span, }; - self.lower_use_tree(use_tree, &prefix, id, vis, name, attrs) + self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { let value = self.lower_body(None, |this| this.lower_expr(e)); @@ -2943,7 +2943,7 @@ impl<'a> LoweringContext<'a> { prefix: &Path, id: NodeId, vis: &mut hir::Visibility, - name: &mut Name, + ident: &mut Ident, attrs: &hir::HirVec<Attribute>, ) -> hir::ItemKind { debug!("lower_use_tree(tree={:?})", tree); @@ -2959,28 +2959,28 @@ impl<'a> LoweringContext<'a> { match tree.kind { UseTreeKind::Simple(rename, id1, id2) => { - *name = tree.ident().name; + *ident = tree.ident(); - // First apply the prefix to the path + // First, apply the prefix to the path. let mut path = Path { segments, span: path.span, }; - // Correctly resolve `self` imports + // Correctly resolve `self` imports. if path.segments.len() > 1 && path.segments.last().unwrap().ident.name == keywords::SelfLower.name() { let _ = path.segments.pop(); if rename.is_none() { - *name = path.segments.last().unwrap().ident.name; + *ident = path.segments.last().unwrap().ident; } } let parent_def_index = self.current_hir_id_owner.last().unwrap().0; let mut defs = self.expect_full_def_from_use(id); - // we want to return *something* from this function, so hang onto the first item - // for later + // We want to return *something* from this function, so hold onto the first item + // for later. let ret_def = defs.next().unwrap_or(Def::Err); // Here, we are looping over namespaces, if they exist for the definition @@ -2990,7 +2990,7 @@ impl<'a> LoweringContext<'a> { // two imports. for (def, &new_node_id) in defs.zip([id1, id2].iter()) { let vis = vis.clone(); - let name = name.clone(); + let ident = ident.clone(); let mut path = path.clone(); for seg in &mut path.segments { seg.id = self.sess.next_node_id(); @@ -3031,7 +3031,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id.node_id, hir_id: new_id.hir_id, - name: name, + ident, attrs: attrs.clone(), node: item, vis, @@ -3057,8 +3057,8 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { - // Nested imports are desugared into simple - // imports. So if we start with + // Nested imports are desugared into simple imports. + // So, if we start with // // ``` // pub(x) use foo::{a, b}; @@ -3079,14 +3079,14 @@ impl<'a> LoweringContext<'a> { // `self.items`. However, the structure of this // function also requires us to return one item, and // for that we return the `{}` import (called the - // "`ListStem`"). + // `ListStem`). let prefix = Path { segments, span: prefix.span.to(path.span), }; - // Add all the nested PathListItems to the HIR. + // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { self.allocate_hir_id_counter(id, &use_tree); @@ -3096,10 +3096,10 @@ impl<'a> LoweringContext<'a> { } = self.lower_node_id(id); let mut vis = vis.clone(); - let mut name = name.clone(); + let mut ident = ident.clone(); let mut prefix = prefix.clone(); - // Give the segments new ids since they are being cloned. + // Give the segments new node-ids since they are being cloned. for seg in &mut prefix.segments { seg.id = self.sess.next_node_id(); } @@ -3114,7 +3114,7 @@ impl<'a> LoweringContext<'a> { &prefix, new_id, &mut vis, - &mut name, + &mut ident, attrs); let vis_kind = match vis.node { @@ -3138,7 +3138,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id, hir_id: new_hir_id, - name, + ident, attrs: attrs.clone(), node: item, vis, @@ -3165,7 +3165,7 @@ impl<'a> LoweringContext<'a> { *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); } hir::VisibilityKind::Restricted { .. } => { - // do nothing here, as described in the comment on the match + // Do nothing here, as described in the comment on the match. } } @@ -3413,7 +3413,7 @@ impl<'a> LoweringContext<'a> { } pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> { - let mut name = i.ident.name; + let mut ident = i.ident; let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { @@ -3421,7 +3421,7 @@ impl<'a> LoweringContext<'a> { attr::contains_name(&i.attrs, "rustc_doc_only_macro") { let body = self.lower_token_stream(def.stream()); self.exported_macros.push(hir::MacroDef { - name, + name: ident.name, vis, attrs, id: i.id, @@ -3433,14 +3433,14 @@ impl<'a> LoweringContext<'a> { return None; } - let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node); + let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); Some(hir::Item { id: node_id, hir_id, - name, + ident, attrs, node, vis, @@ -3453,7 +3453,7 @@ impl<'a> LoweringContext<'a> { let def_id = self.resolver.definitions().local_def_id(node_id); hir::ForeignItem { id: node_id, - name: i.ident.name, + ident: i.ident, attrs: self.lower_attrs(&i.attrs), node: match i.node { ForeignItemKind::Fn(ref fdec, ref generics) => { diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 895e1e782ab6e..837a20ac0f2f0 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -228,7 +228,7 @@ impl<'a> FnLikeNode<'a> { ast::ItemKind::Fn(ref decl, header, ref generics, block) => item_fn(ItemFnParts { id: i.id, - name: i.name, + name: i.ident.name, decl: &decl, body: block, vis: &i.vis, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d7c51f1e5fd36..188d487d64485 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -813,11 +813,11 @@ impl<'hir> Map<'hir> { /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { - Node::Item(i) => i.name, - Node::ForeignItem(i) => i.name, + Node::Item(i) => i.ident.name, + Node::ForeignItem(fi) => fi.ident.name, Node::ImplItem(ii) => ii.ident.name, Node::TraitItem(ti) => ti.ident.name, - Node::Variant(v) => v.node.name, + Node::Variant(v) => v.node.ident.name, Node::Field(f) => f.ident.name, Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, @@ -953,7 +953,7 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { loop { if let Node::Item(item) = map.find(id)? { if item_is_mod(&item) { - return Some((id, item.name)) + return Some((id, item.ident.name)) } } let parent = map.get_parent(id); @@ -1009,9 +1009,9 @@ trait Named { impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } } -impl Named for Item { fn name(&self) -> Name { self.name } } -impl Named for ForeignItem { fn name(&self) -> Name { self.name } } -impl Named for VariantKind { fn name(&self) -> Name { self.name } } +impl Named for Item { fn name(&self) -> Name { self.ident.name } } +impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } +impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } } impl Named for StructField { fn name(&self) -> Name { self.ident.name } } impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } @@ -1194,7 +1194,7 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { } Some(Node::Variant(ref variant)) => { format!("variant {} in {}{}", - variant.node.name, + variant.node.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 56144129ef4c2..969e1c3620eb7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2015,7 +2015,7 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct VariantKind { - pub name: Name, + pub ident: Ident, pub attrs: HirVec<Attribute>, pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1` @@ -2176,7 +2176,7 @@ pub struct ItemId { /// The name might be a dummy name in case of anonymous items #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { - pub name: Name, + pub ident: Ident, pub id: NodeId, pub hir_id: HirId, pub attrs: HirVec<Attribute>, @@ -2331,7 +2331,7 @@ pub enum AssociatedItemKind { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignItem { - pub name: Name, + pub ident: Ident, pub attrs: HirVec<Attribute>, pub node: ForeignItemKind, pub id: NodeId, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e19da011be1d6..d7acdefcc7d71 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -452,7 +452,7 @@ impl<'a> State<'a> { abi: Abi::Rust, asyncness: hir::IsAsync::NotAsync, }, - Some(item.name), + Some(item.ident.name), generics, &item.vis, arg_names, @@ -466,7 +466,7 @@ impl<'a> State<'a> { if m { self.word_space("mut")?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&t)?; self.s.word(";")?; @@ -475,7 +475,7 @@ impl<'a> State<'a> { } hir::ForeignItemKind::Type => { self.head(visibility_qualified(&item.vis, "type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox @@ -535,7 +535,7 @@ impl<'a> State<'a> { self.s.word("as")?; self.s.space()?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block @@ -546,10 +546,10 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { - if path.segments.last().unwrap().ident.name != item.name { + if path.segments.last().unwrap().ident != item.ident { self.s.space()?; self.word_space("as")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; } self.s.word(";")?; } @@ -564,7 +564,7 @@ impl<'a> State<'a> { if m == hir::MutMutable { self.word_space("mut")?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&ty)?; self.s.space()?; @@ -577,7 +577,7 @@ impl<'a> State<'a> { } hir::ItemKind::Const(ref ty, expr) => { self.head(visibility_qualified(&item.vis, "const"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&ty)?; self.s.space()?; @@ -592,7 +592,7 @@ impl<'a> State<'a> { self.head("")?; self.print_fn(decl, header, - Some(item.name), + Some(item.ident.name), typarams, &item.vis, &[], @@ -604,7 +604,7 @@ impl<'a> State<'a> { } hir::ItemKind::Mod(ref _mod) => { self.head(visibility_qualified(&item.vis, "mod"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.nbsp()?; self.bopen()?; self.print_mod(_mod, &item.attrs)?; @@ -624,7 +624,7 @@ impl<'a> State<'a> { } hir::ItemKind::Ty(ref ty, ref generics) => { self.head(visibility_qualified(&item.vis, "type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -637,7 +637,7 @@ impl<'a> State<'a> { } hir::ItemKind::Existential(ref exist) => { self.head(visibility_qualified(&item.vis, "existential type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&exist.generics.params)?; self.end()?; // end the inner ibox @@ -659,15 +659,16 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } hir::ItemKind::Enum(ref enum_definition, ref params) => { - self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?; + self.print_enum_def(enum_definition, params, item.ident.name, item.span, + &item.vis)?; } hir::ItemKind::Struct(ref struct_def, ref generics) => { self.head(visibility_qualified(&item.vis, "struct"))?; - self.print_struct(struct_def, generics, item.name, item.span, true)?; + self.print_struct(struct_def, generics, item.ident.name, item.span, true)?; } hir::ItemKind::Union(ref struct_def, ref generics) => { self.head(visibility_qualified(&item.vis, "union"))?; - self.print_struct(struct_def, generics, item.name, item.span, true)?; + self.print_struct(struct_def, generics, item.ident.name, item.span, true)?; } hir::ItemKind::Impl(unsafety, polarity, @@ -714,7 +715,7 @@ impl<'a> State<'a> { self.print_is_auto(is_auto)?; self.print_unsafety(unsafety)?; self.word_nbsp("trait")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { @@ -739,7 +740,7 @@ impl<'a> State<'a> { self.head("")?; self.print_visibility(&item.vis)?; self.word_nbsp("trait")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax @@ -897,7 +898,7 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> { self.head("")?; let generics = hir::Generics::empty(); - self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; + self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false)?; if let Some(ref d) = v.node.disr_expr { self.s.space()?; self.word_space("=")?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index bf9efb54b600f..8ff60e5f56225 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -818,7 +818,7 @@ impl_stable_hash_for!(struct hir::EnumDef { }); impl_stable_hash_for!(struct hir::VariantKind { - name, + ident -> (ident.name), attrs, data, disr_expr @@ -852,7 +852,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Item { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher<W>) { let hir::Item { - name, + ident, ref attrs, id: _, hir_id: _, @@ -862,7 +862,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Item { } = *self; hcx.hash_hir_item_like(|hcx| { - name.hash_stable(hcx, hasher); + ident.name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher); @@ -926,7 +926,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::AssociatedItemKind { } impl_stable_hash_for!(struct hir::ForeignItem { - name, + ident -> (ident.name), attrs, node, id, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 3cc9bffa9a423..0c769c91801b8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -557,7 +557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { self.warn_dead_code( item.id, span, - item.name, + item.ident.name, item.node.descriptive_variant(), participle, ); @@ -572,7 +572,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { g: &'tcx hir::Generics, id: ast::NodeId) { if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.name, + self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.ident.name, "variant", "constructed"); } else { intravisit::walk_variant(self, variant, g, id); @@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) { if self.should_warn_about_foreign_item(fi) { - self.warn_dead_code(fi.id, fi.span, fi.name, + self.warn_dead_code(fi.id, fi.span, fi.ident.name, fi.node.descriptive_variant(), "used"); } intravisit::walk_foreign_item(self, fi); diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 2add525f0940d..6b593a1a9f9b2 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -86,7 +86,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, "main") { EntryPointType::MainAttr - } else if item.name == "main" { + } else if item.ident.name == "main" { if at_root { // This is a top-level function so can be 'main'. EntryPointType::MainNamed diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f774b13f98301..36d51c5971278 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2040,7 +2040,7 @@ impl<'tcx> Debug for Place<'tcx> { Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1), Projection(ref data) => match data.elem { ProjectionElem::Downcast(ref adt_def, index) => { - write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name) + write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident) } ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base), ProjectionElem::Field(field, ty) => { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a5331cbbdb0e5..171c53b7b20ba 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,7 +1,7 @@ use session::{self, DataTypeKind}; use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; -use syntax::ast::{self, IntTy, UintTy}; +use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; @@ -1228,7 +1228,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let adt_kind = adt_def.adt_kind(); let adt_packed = adt_def.repr.packed(); - let build_variant_info = |n: Option<ast::Name>, + let build_variant_info = |n: Option<Ident>, flds: &[ast::Name], layout: TyLayout<'tcx>| { let mut min_size = Size::ZERO; @@ -1273,7 +1273,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { match layout.variants { Variants::Single { index } => { debug!("print-type-size `{:#?}` variant {}", - layout, adt_def.variants[index].name); + layout, adt_def.variants[index].ident); if !adt_def.variants.is_empty() { let variant_def = &adt_def.variants[index]; let fields: Vec<_> = @@ -1281,7 +1281,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { record(adt_kind.into(), adt_packed, None, - vec![build_variant_info(Some(variant_def.name), + vec![build_variant_info(Some(variant_def.ident), &fields, layout)]); } else { @@ -1299,7 +1299,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { adt_def.variants.iter_enumerated().map(|(i, variant_def)| { let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); - build_variant_info(Some(variant_def.name), + build_variant_info(Some(variant_def.ident), &fields, layout.for_variant(self, i)) }) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fd8a7db1b4760..8348aa8a95612 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1780,7 +1780,7 @@ pub struct VariantDef { /// The variant's `DefId`. If this is a tuple-like struct, /// this is the `DefId` of the struct's ctor. pub did: DefId, - pub name: Name, // struct's name if this is a struct + pub ident: Ident, // struct's name if this is a struct pub discr: VariantDiscr, pub fields: Vec<FieldDef>, pub ctor_kind: CtorKind, @@ -1804,7 +1804,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { /// remove this hack and use the constructor DefId everywhere. pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, did: DefId, - name: Name, + ident: Ident, discr: VariantDiscr, fields: Vec<FieldDef>, adt_kind: AdtKind, @@ -1812,7 +1812,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { attribute_def_id: DefId) -> Self { - debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, name, discr, + debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr, fields, adt_kind, ctor_kind, attribute_def_id); let mut flags = VariantFlags::NO_VARIANT_FLAGS; if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") { @@ -1821,7 +1821,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { } VariantDef { did, - name, + ident, discr, fields, ctor_kind, @@ -1837,7 +1837,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { impl_stable_hash_for!(struct VariantDef { did, - name, + ident -> (ident.name), discr, fields, ctor_kind, @@ -1978,8 +1978,6 @@ impl_stable_hash_for!(struct ReprFlags { bits }); - - /// Represents the repr options provided by the user, #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3be784ccc04b0..0fd04e9d20393 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1215,7 +1215,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { name: if fallback { String::new() } else { - adt.variants[index].name.as_str().to_string() + adt.variants[index].ident.as_str().to_string() }, type_metadata: variant_type_metadata, offset: Size::ZERO, @@ -1255,7 +1255,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { name: if fallback { String::new() } else { - adt.variants[i].name.as_str().to_string() + adt.variants[i].ident.as_str().to_string() }, type_metadata: variant_type_metadata, offset: Size::ZERO, @@ -1321,7 +1321,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.layout, self.layout.fields.offset(0), self.layout.field(cx, 0).size); - name.push_str(&adt.variants[*niche_variants.start()].name.as_str()); + name.push_str(&adt.variants[*niche_variants.start()].ident.as_str()); // Create the (singleton) list of descriptions of union members. vec![ @@ -1365,7 +1365,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { }; MemberDescription { - name: adt.variants[i].name.as_str().to_string(), + name: adt.variants[i].ident.as_str().to_string(), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1433,7 +1433,7 @@ fn describe_enum_variant( containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { - let variant_name = variant.name.as_str(); + let variant_name = variant.ident.as_str(); let unique_type_id = debug_context(cx).type_map .borrow_mut() .get_unique_type_id_of_enum_variant( @@ -1527,7 +1527,7 @@ fn prepare_enum_metadata( let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) .map(|((_, discr), v)| { - let name = SmallCStr::new(&v.name.as_str()); + let name = SmallCStr::new(&v.ident.as_str()); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index bac2294bd31c7..97128c2d2a2ce 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -60,7 +60,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, = (&layout.ty.sty, &layout.variants) { if def.is_enum() && !def.variants.is_empty() { - write!(&mut name, "::{}", def.variants[index].name).unwrap(); + write!(&mut name, "::{}", def.variants[index].ident).unwrap(); } } Some(name) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index a8cc401ac38ee..a5f7d676862e0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -261,7 +261,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { assert!(idx < names.len()); for item in &m.item_ids { let item = this.infcx.tcx.hir().expect_item(item.id); - if item.name.to_string() == names[idx] { + if item.ident.to_string() == names[idx] { return search(this, item, idx + 1, names); } } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index e425d2cdae9a7..2694a04b94ce4 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemKind::Mod(_) = it.node { - self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span)); + self.check_snake_case(cx, "module", &it.ident.as_str(), Some(it.span)); } } @@ -354,10 +354,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { if attr::find_by_name(&it.attrs, "no_mangle").is_some() { return; } - NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span); + NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.ident.name, + it.span); } hir::ItemKind::Const(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span); + NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident.name, + it.span); } _ => {} } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 65e1b9ff7628b..642681a73a8a0 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -837,7 +837,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let bytes = variant_layout.size.bytes().saturating_sub(discr_size); debug!("- variant `{}` is {} bytes large", - variant.node.name, + variant.node.ident, bytes); bytes }) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 687753bd8de08..dc8db5be5820a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -553,7 +553,7 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef::new( tcx, def_id, - self.item_name(index).as_symbol(), + Ident::from_interned_str(self.item_name(index)), data.discr, item.children.decode(self).map(|index| { let f = self.entry(index); diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 50d861b674cef..f758e48887715 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -306,7 +306,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor, pat: &Pat) { let pat_ty = cx.tables.pat_ty(p); if let ty::Adt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { - variant.name == ident.name && variant.ctor_kind == CtorKind::Const + variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { let ty_path = cx.tcx.item_path_str(edef.did); let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 92da0563d8091..62ec52aac1346 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -280,7 +280,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { let mut start_or_continue = || if first { first = false; "" } else { ", " }; if let Some(variant) = variant { - write!(f, "{}", variant.name)?; + write!(f, "{}", variant.ident)?; // Only for Adt we can have `S {...}`, // which we handle separately here. diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 5e006e20e4785..a5fb44587400a 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -246,7 +246,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> variant_id: VariantIdx, new_op: OpTy<'tcx, M::PointerTag> ) -> EvalResult<'tcx> { - let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name; + let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].ident.name; self.visit_elem(new_op, PathElem::Variant(name)) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5f6ef934c1aa3..8454dbc3410c9 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -304,7 +304,7 @@ impl<'a> Resolver<'a> { let features = self.session.features_untracked(); if attr_kind == NonMacroAttrKind::Custom { assert!(path.segments.len() == 1); - let name = path.segments[0].ident.name.as_str(); + let name = path.segments[0].ident.as_str(); if name.starts_with("rustc_") { if !features.rustc_attrs { let msg = "unless otherwise specified, attributes with the prefix \ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 736b416dd4f21..f33060dde4f15 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1322,8 +1322,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { span, &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), ); - // Check if it was a typo - let input = adt_def.variants.iter().map(|variant| &variant.name); + // Check if it was a typo. + let input = adt_def.variants.iter().map(|variant| &variant.ident.name); if let Some(suggested_name) = find_best_match_for_name( input, &assoc_name.as_str(), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f227c529cb035..4e3cb5c7f1c0d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -952,7 +952,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); if plural == "" { let input = unmentioned_fields.iter().map(|field| &field.name); let suggested_name = - find_best_match_for_name(input, &ident.name.as_str(), None); + find_best_match_for_name(input, &ident.as_str(), None); if let Some(suggested_name) = suggested_name { err.span_suggestion(*span, "did you mean", suggested_name.to_string()); // we don't want to throw `E0027` in case we have thrown `E0026` for them diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index c80990a0704bd..a36b21921436e 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -71,7 +71,7 @@ fn equate_intrinsic_type<'a, 'tcx>( pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); - let name = it.name.as_str(); + let name = it.ident.as_str(); let mk_va_list_ty = || { tcx.lang_items().va_list().map(|did| { @@ -393,7 +393,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def_id = tcx.hir().local_def_id(it.id); let i_n_tps = tcx.generics_of(def_id).own_counts().types; - let name = it.name.as_str(); + let name = it.ident.as_str(); let (n_tps, inputs, output) = match &*name { "simd_eq" | "simd_ne" | "simd_lt" | "simd_le" | "simd_gt" | "simd_ge" => { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index c4a908d56f351..65a58d345ccfa 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -185,7 +185,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "method" } else if actual.is_enum() { if let Adt(ref adt_def, _) = actual.sty { - let names = adt_def.variants.iter().map(|s| &s.name); + let names = adt_def.variants.iter().map(|s| &s.ident.name); suggestion = find_best_match_for_name(names, &item_name.as_str(), None); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b3c24be108da7..65e662f74fb41 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1327,7 +1327,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite } hir::ItemKind::Fn(..) => {} // entirely within check_item_body hir::ItemKind::Impl(.., ref impl_item_refs) => { - debug!("ItemKind::Impl {} with id {}", it.name, it.id); + debug!("ItemKind::Impl {} with id {}", it.ident, it.id); let impl_def_id = tcx.hir().local_def_id(it.id); if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { check_impl_items_against_trait( @@ -3529,7 +3529,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Adt(adt, ..) if adt.is_enum() => { struct_span_err!(self.tcx.sess, field.ident.span, E0559, "{} `{}::{}` has no field named `{}`", - kind_name, actual, variant.name, field.ident) + kind_name, actual, variant.ident, field.ident) } _ => { struct_span_err!(self.tcx.sess, field.ident.span, E0560, @@ -3551,7 +3551,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if adt.is_enum() { err.span_label(field.ident.span, format!("`{}::{}` does not have this field", - ty, variant.name)); + ty, variant.ident)); } else { err.span_label(field.ident.span, format!("`{}` does not have this field", ty)); @@ -4811,13 +4811,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let parent = self.tcx.hir().get(fn_id); if let Node::Item(&hir::Item { - name, node: hir::ItemKind::Fn(ref decl, ..), .. + ident, node: hir::ItemKind::Fn(ref decl, ..), .. }) = parent { decl.clone().and_then(|decl| { // This is less than ideal, it will not suggest a return type span on any // method called `main`, regardless of whether it is actually the entry point, // but it will still present it as the reason for the expected type. - Some((decl, name != Symbol::intern("main"))) + Some((decl, ident.name != Symbol::intern("main"))) }) } else if let Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(hir::MethodSig { diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 740e64b1895e8..bf767726ef715 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -154,7 +154,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { // If the extern crate isn't in the extern prelude, // there is no way it can be written as an `use`. - let orig_name = extern_crate.orig_name.unwrap_or(item.name); + let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name); if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) { continue; } @@ -173,8 +173,8 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { visibility_qualified(&item.vis, "use") ); let base_replacement = match extern_crate.orig_name { - Some(orig_name) => format!("use {} as {};", orig_name, item.name), - None => format!("use {};", item.name), + Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), + None => format!("use {};", item.ident.name), }; let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_node(lint, id, extern_crate.span, msg) @@ -219,7 +219,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> { def_id: extern_crate_def_id, span: item.span, orig_name, - warn_if_unused: !item.name.as_str().starts_with('_'), + warn_if_unused: !item.ident.as_str().starts_with('_'), } ); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 54dfc57bac674..9fc2f11b19738 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -33,7 +33,7 @@ use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; -use syntax::ast::MetaItemKind; +use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, list_contains_name, mark_used}; use syntax::source_map::Spanned; use syntax::feature_gate; @@ -385,7 +385,7 @@ fn is_param<'a, 'tcx>( fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { let it = tcx.hir().expect_item(item_id); - debug!("convert: item {} with id {}", it.name, it.id); + debug!("convert: item {} with id {}", it.ident, it.id); let def_id = tcx.hir().local_def_id(item_id); match it.node { // These don't define types. @@ -533,7 +533,7 @@ fn convert_enum_variant_types<'a, 'tcx>( format!("overflowed on value after {}", prev_discr.unwrap()), ).note(&format!( "explicitly set `{} = {}` if that is desired outcome", - variant.node.name, wrapped_discr + variant.node.ident, wrapped_discr )) .emit(); None @@ -556,7 +556,7 @@ fn convert_enum_variant_types<'a, 'tcx>( fn convert_variant<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, - name: ast::Name, + ident: Ident, discr: ty::VariantDiscr, def: &hir::VariantData, adt_kind: ty::AdtKind, @@ -593,12 +593,13 @@ fn convert_variant<'a, 'tcx>( .collect(); ty::VariantDef::new(tcx, did, - name, + ident, discr, fields, adt_kind, CtorKind::from_hir(def), - attribute_def_id) + attribute_def_id + ) } fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef { @@ -628,7 +629,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad }; distance_from_explicit += 1; - convert_variant(tcx, did, v.node.name, discr, &v.node.data, AdtKind::Enum, + convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum, did) }) .collect(), @@ -646,7 +647,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad std::iter::once(convert_variant( tcx, ctor_id.unwrap_or(def_id), - item.name, + item.ident, ty::VariantDiscr::Relative(0), def, AdtKind::Struct, @@ -659,7 +660,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad std::iter::once(convert_variant( tcx, def_id, - item.name, + item.ident, ty::VariantDiscr::Relative(0), def, AdtKind::Union, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 54d3e640ec585..38b2452b420e9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2967,7 +2967,7 @@ impl<'tcx> Clean<Item> for ty::VariantDef { } }; Item { - name: Some(self.name.clean(cx)), + name: Some(self.ident.clean(cx)), attrs: inline::load_attrs(cx, self.did), source: cx.tcx.def_span(self.did).clean(cx), visibility: Some(Inherited), @@ -3183,13 +3183,22 @@ fn qpath_to_string(p: &hir::QPath) -> String { s } +impl Clean<String> for Ident { + #[inline] + fn clean(&self, cx: &DocContext) -> String { + self.name.clean(cx) + } +} + impl Clean<String> for ast::Name { + #[inline] fn clean(&self, _: &DocContext) -> String { self.to_string() } } impl Clean<String> for InternedString { + #[inline] fn clean(&self, _: &DocContext) -> String { self.to_string() } @@ -3616,7 +3625,7 @@ impl Clean<Item> for hir::ForeignItem { }; Item { - name: Some(self.name.clean(cx)), + name: Some(self.ident.clean(cx)), attrs: self.attrs.clean(cx), source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), @@ -3951,7 +3960,7 @@ pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> { for item_id in mem::replace(&mut items, HirVec::new()).iter() { let item = tcx.hir().expect_item(item_id.id); - if item.name == *segment { + if item.ident.name == *segment { if path_it.peek().is_none() { return Some(tcx.hir().local_def_id(item_id.id)) } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index b8ec7e4bd32ab..fdc1c0616187a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -632,7 +632,7 @@ fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option<String>), () }; let parent_def = Def::Enum(parent); let variant = cx.tcx.expect_variant_def(def); - Ok((parent_def, Some(format!("{}.v", variant.name)))) + Ok((parent_def, Some(format!("{}.v", variant.ident.name)))) } const PRIMITIVES: &[(&str, Def)] = &[ diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4d870daac4d03..24bb00f411242 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -811,7 +811,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.node { self.map.node_to_pretty_string(ty.id) } else { - item.name.to_string() + item.ident.to_string() }; self.visit_testable(name, &item.attrs, |this| { @@ -832,7 +832,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { } fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem) { - self.visit_testable(item.name.to_string(), &item.attrs, |this| { + self.visit_testable(item.ident.to_string(), &item.attrs, |this| { intravisit::walk_foreign_item(this, item); }); } @@ -841,7 +841,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { v: &'hir hir::Variant, g: &'hir hir::Generics, item_id: ast::NodeId) { - self.visit_testable(v.node.name.to_string(), &v.node.attrs, |this| { + self.visit_testable(v.node.ident.to_string(), &v.node.attrs, |this| { intravisit::walk_variant(this, v, g, item_id); }); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ffdc048a30ece..953ab7c2565bf 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { Enum { name, variants: def.variants.iter().map(|v| Variant { - name: v.node.name, + name: v.node.ident.name, attrs: v.node.attrs.clone(), stab: self.stability(v.node.data.id()), depr: self.deprecation(v.node.data.id()), @@ -263,7 +263,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { fn maybe_inline_local(&mut self, id: ast::NodeId, def: Def, - renamed: Option<ast::Name>, + renamed: Option<ast::Ident>, glob: bool, om: &mut Module, please_inline: bool) -> bool { @@ -357,14 +357,14 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { om.foreigns.push(hir::ForeignMod { abi: tcx.hir().get_foreign_abi(it.id), items: vec![hir::ForeignItem { - name: renamed.unwrap_or(it.name), + ident: renamed.unwrap_or(it.ident), .. it.clone() }].into(), }); true } Node::MacroDef(def) if !glob => { - om.macros.push(self.visit_local_macro(def, renamed)); + om.macros.push(self.visit_local_macro(def, renamed.map(|i| i.name))); true } _ => false, @@ -374,9 +374,9 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { } pub fn visit_item(&mut self, item: &hir::Item, - renamed: Option<ast::Name>, om: &mut Module) { + renamed: Option<ast::Ident>, om: &mut Module) { debug!("Visiting item {:?}", item); - let name = renamed.unwrap_or(item.name); + let ident = renamed.unwrap_or(item.ident); if item.vis.node.is_pub() { let def_id = self.cx.tcx.hir().local_def_id(item.id); @@ -403,7 +403,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { om.extern_crates.push(ExternCrate { cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id) .unwrap_or(LOCAL_CRATE), - name, + name: ident.name, path: orig_name.map(|x|x.to_string()), vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -433,10 +433,10 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { _ => false, } }); - let name = if is_glob { None } else { Some(name) }; + let ident = if is_glob { None } else { Some(ident) }; if self.maybe_inline_local(item.id, path.def, - name, + ident, is_glob, om, please_inline) { @@ -445,7 +445,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { } om.imports.push(Import { - name, + name: ident.name, id: item.id, vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -460,21 +460,21 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { item.vis.clone(), item.id, m, - Some(name))); + Some(ident.name))); }, hir::ItemKind::Enum(ref ed, ref gen) => - om.enums.push(self.visit_enum_def(item, name, ed, gen)), + om.enums.push(self.visit_enum_def(item, ident.name, ed, gen)), hir::ItemKind::Struct(ref sd, ref gen) => - om.structs.push(self.visit_variant_data(item, name, sd, gen)), + om.structs.push(self.visit_variant_data(item, ident.name, sd, gen)), hir::ItemKind::Union(ref sd, ref gen) => - om.unions.push(self.visit_union_data(item, name, sd, gen)), + om.unions.push(self.visit_union_data(item, ident.name, sd, gen)), hir::ItemKind::Fn(ref fd, header, ref gen, body) => - self.visit_fn(om, item, name, &**fd, header, gen, body), + self.visit_fn(om, item, ident.name, &**fd, header, gen, body), hir::ItemKind::Ty(ref ty, ref gen) => { let t = Typedef { ty: ty.clone(), gen: gen.clone(), - name, + name: ident.name, id: item.id, attrs: item.attrs.clone(), whence: item.span, @@ -487,7 +487,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { hir::ItemKind::Existential(ref exist_ty) => { let t = Existential { exist_ty: exist_ty.clone(), - name, + name: ident.name, id: item.id, attrs: item.attrs.clone(), whence: item.span, @@ -503,7 +503,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { mutability: mut_.clone(), expr: exp.clone(), id: item.id, - name, + name: ident.name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -517,7 +517,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { type_: ty.clone(), expr: exp.clone(), id: item.id, - name, + name: ident.name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -533,7 +533,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { let t = Trait { is_auto, unsafety, - name, + name: ident.name, items, generics: gen.clone(), bounds: b.iter().cloned().collect(), diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs new file mode 100644 index 0000000000000..efef4ab00aed2 --- /dev/null +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -0,0 +1,51 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![feature(plugin_registrar)] +#![feature(box_syntax, rustc_private)] + +// Load rustc as a plugin to get macros. +#[macro_use] +extern crate rustc; +extern crate rustc_plugin; + +use rustc::hir; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc_plugin::Registry; + +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); + +struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(TEST_LINT, PLEASE_LINT) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + match &*it.ident.as_str() { + "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), + "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), + _ => {} + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_late_lint_pass(box Pass); + reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]); +} diff --git a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs index 91d03d98a10b9..bca1d7a72b4ab 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -3,7 +3,7 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -// Load rustc as a plugin to get macros +// Load rustc as a plugin to get macros. #[macro_use] extern crate rustc; extern crate rustc_plugin; @@ -26,7 +26,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match &*it.name.as_str() { + match &*it.ident.as_str() { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), _ => {} diff --git a/src/test/ui-fulldeps/lint-group-plugin.rs b/src/test/ui-fulldeps/lint-group-plugin.rs index 00c5a56a482c1..7a650afe5f8fa 100644 --- a/src/test/ui-fulldeps/lint-group-plugin.rs +++ b/src/test/ui-fulldeps/lint-group-plugin.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:lint_group_plugin_test.rs // ignore-stage1 + #![feature(plugin)] #![plugin(lint_group_plugin_test)] #![allow(dead_code)] diff --git a/src/test/ui-fulldeps/lint-group-plugin.stderr b/src/test/ui-fulldeps/lint-group-plugin.stderr index 15cffedcc5d3c..b566048c75ee6 100644 --- a/src/test/ui-fulldeps/lint-group-plugin.stderr +++ b/src/test/ui-fulldeps/lint-group-plugin.stderr @@ -1,5 +1,5 @@ warning: item is named 'lintme' - --> $DIR/lint-group-plugin.rs:8:1 + --> $DIR/lint-group-plugin.rs:9:1 | LL | fn lintme() { } //~ WARNING item is named 'lintme' | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn lintme() { } //~ WARNING item is named 'lintme' = note: #[warn(test_lint)] on by default warning: item is named 'pleaselintme' - --> $DIR/lint-group-plugin.rs:9:1 + --> $DIR/lint-group-plugin.rs:10:1 | LL | fn pleaselintme() { } //~ WARNING item is named 'pleaselintme' | ^^^^^^^^^^^^^^^^^^^^^ From 4748dc5e778134ac6c32805c9733986a5ef44f93 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Mon, 3 Dec 2018 21:50:49 +0000 Subject: [PATCH 008/124] Implemented variants on type aliases in both ctor and pattern position. --- src/librustc_mir/hair/cx/expr.rs | 5 +- src/librustc_typeck/astconv.rs | 24 +++++- src/librustc_typeck/check/method/mod.rs | 35 ++++++-- src/librustc_typeck/check/mod.rs | 106 +++++++++++++++++++----- src/librustc_typeck/lib.rs | 26 ++++++ src/libsyntax/feature_gate.rs | 5 +- 6 files changed, 166 insertions(+), 35 deletions(-) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 23cfd18ef5d4c..7b1ed2b0b26ea 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -481,10 +481,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } AdtKind::Enum => { - let def = match *qpath { - hir::QPath::Resolved(_, ref path) => path.def, - hir::QPath::TypeRelative(..) => Def::Err, - }; + let def = cx.tables().qpath_def(qpath, expr.hir_id); match def { Def::Variant(variant_id) => { assert!(base.is_none()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f33060dde4f15..18c19352a603b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -31,6 +31,8 @@ use std::collections::BTreeSet; use std::iter; use std::slice; +use super::{allow_type_alias_enum_variants}; + pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -1275,6 +1277,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ref_id: ast::NodeId, span: Span, ty: Ty<'tcx>, + ty_hir: &hir::Ty, ty_path_def: Def, item_segment: &hir::PathSegment) -> (Ty<'tcx>, Def) @@ -1286,6 +1289,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(slice::from_ref(item_segment)); + // Check if we have an enum variant here. + if let ty::Adt(adt_def, _) = ty.sty { + if adt_def.is_enum() { + if allow_type_alias_enum_variants(tcx, ty_hir, span) { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + let def = Def::Variant(variant_def.did); + return (ty, def); + } + } + } + } + // Find the type of the associated item, and the trait where the associated // item is declared. let bound = match (&ty.sty, ty_path_def) { @@ -1342,7 +1360,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { return (tcx.types.err, Def::Err); } _ => { - // Don't print TyErr to the user. + // Don't print `TyErr` to the user. if !ty.references_error() { self.report_ambiguous_associated_type(span, &ty.to_string(), @@ -1505,10 +1523,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } Def::SelfTy(_, Some(def_id)) => { // `Self` in impl (we know the concrete type) - assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - tcx.at(span).type_of(def_id) } Def::SelfTy(Some(_), None) => { @@ -1602,7 +1618,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 + self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, qself, def, segment).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 2bc1dfaf04e37..f594690f77f02 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -1,4 +1,4 @@ -//! Method lookup: the secret sauce of Rust. See the [rustc guide] chapter. +//! Method lookup: the secret sauce of Rust. See the [rustc guide] for more information. //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html @@ -25,6 +25,7 @@ use rustc::infer::{self, InferOk}; use syntax::ast; use syntax_pos::Span; +use crate::{allow_type_alias_enum_variants}; use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { @@ -360,21 +361,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, method_name: ast::Ident, self_ty: Ty<'tcx>, + self_ty_hir: &hir::Ty, expr_id: ast::NodeId) -> Result<Def, MethodError<'tcx>> { + debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", + method_name, + self_ty, + expr_id + ); + + let tcx = self.tcx; + + // Check if we have an enum variant here. + if let ty::Adt(adt_def, _) = self_ty.sty { + if adt_def.is_enum() { + if allow_type_alias_enum_variants(tcx, self_ty_hir, span) { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + return Ok(def); + } + } + } + } + let mode = probe::Mode::Path; let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false), self_ty, expr_id, ProbeScope::TraitsInScope)?; if let Some(import_id) = pick.import_id { - let import_def_id = self.tcx.hir().local_def_id(import_id); - debug!("used_trait_import: {:?}", import_def_id); + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + .unwrap().insert(import_def_id); } let def = pick.item.def(); - self.tcx.check_stability(def.def_id(), Some(expr_id), span); + tcx.check_stability(def.def_id(), Some(expr_id), span); Ok(def) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 65e662f74fb41..686365648f00d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -101,14 +101,14 @@ use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; -use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, - UserSelfTy, UserSubsts}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, RegionKind, Visibility, ToPolyTraitRef, ToPredicate}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; +use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, + UserSelfTy, UserSubsts}; use rustc::ty::util::{Representability, IntTypeExt, Discr}; use rustc::ty::layout::VariantIdx; use syntax_pos::{self, BytePos, Span, MultiSpan}; @@ -4542,7 +4542,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Err }; let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, def, segment); + ty, qself, def, segment); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); @@ -4561,14 +4561,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) { - let (ty, item_segment) = match *qpath { + let (ty, ty_hir, item_segment) = match *qpath { hir::QPath::Resolved(ref opt_qself, ref path) => { return (path.def, opt_qself.as_ref().map(|qself| self.to_ty(qself)), &path.segments[..]); } hir::QPath::TypeRelative(ref qself, ref segment) => { - (self.to_ty(qself), segment) + (self.to_ty(qself), qself, segment) } }; let hir_id = self.tcx.hir().node_to_hir_id(node_id); @@ -4578,7 +4578,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return (*cached_def, Some(ty), slice::from_ref(&**item_segment)) } let item_name = item_segment.ident; - let def = match self.resolve_ufcs(span, item_name, ty, node_id) { + let def = match self.resolve_ufcs(span, item_name, ty, ty_hir, node_id) { Ok(def) => def, Err(error) => { let def = match error { @@ -5040,6 +5040,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn def_ids_for_path_segments(&self, segments: &[hir::PathSegment], + self_ty: Option<Ty<'tcx>>, def: Def) -> Vec<PathSeg> { // We need to extract the type parameters supplied by the user in @@ -5051,15 +5052,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // There are basically four cases to consider: // - // 1. Reference to a constructor of enum variant or struct: + // 1. Reference to a constructor of a struct: // // struct Foo<T>(...) + // + // In this case, the parameters are declared in the type space. + // + // 2. Reference to a constructor of an enum variant: + // // enum E<T> { Foo(...) } // - // In these cases, the parameters are declared in the type - // space. + // In this case, the parameters are defined in the type space, + // but may be specified either on the type or the variant. // - // 2. Reference to a fn item or a free constant: + // 3. Reference to a fn item or a free constant: // // fn foo<T>() { } // @@ -5068,7 +5074,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters. However, in this case, those parameters are // declared on a value, and hence are in the `FnSpace`. // - // 3. Reference to a method or an associated constant: + // 4. Reference to a method or an associated constant: // // impl<A> SomeStruct<A> { // fn foo<B>(...) @@ -5080,7 +5086,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `SomeStruct::<A>`, contains parameters in TypeSpace, and the // final segment, `foo::<B>` contains parameters in fn space. // - // 4. Reference to a local variable + // 5. Reference to a local variable // // Local variables can't have any type parameters. // @@ -5092,9 +5098,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut path_segs = vec![]; match def { - // Case 1. Reference to a struct/variant constructor. + // Case 1. Reference to a struct constructor. Def::StructCtor(def_id, ..) | - Def::VariantCtor(def_id, ..) | Def::SelfCtor(.., def_id) => { // Everything but the final segment should have no // parameters at all. @@ -5105,14 +5110,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { path_segs.push(PathSeg(generics_def_id, last)); } - // Case 2. Reference to a top-level value. + // Case 2. Reference to a variant constructor. + Def::VariantCtor(def_id, ..) => { + if tcx.features().type_alias_enum_variants { + let adt_def = self_ty.and_then(|t| t.ty_adt_def()); + let (generics_def_id, index) = if let Some(adt_def) = adt_def { + debug_assert!(adt_def.is_enum()); + (adt_def.did, last) + } else if last >= 1 && segments[last - 1].args.is_some() { + // Everything but the penultimate segment should have no + // parameters at all. + let enum_def_id = self.tcx.parent_def_id(def_id).unwrap(); + (enum_def_id, last - 1) + } else { + // FIXME: lint here suggesting `Enum::<...>::Variant` form + // instead of `Enum::Variant::<...>` form. + + // Everything but the final segment should have no + // parameters at all. + let generics = self.tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + (generics.parent.unwrap_or(def_id), last) + }; + path_segs.push(PathSeg(generics_def_id, index)); + } else { + // Everything but the final segment should have no + // parameters at all. + let generics = self.tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + let generics_def_id = generics.parent.unwrap_or(def_id); + path_segs.push(PathSeg(generics_def_id, last)); + } + } + + // Case 3. Reference to a top-level value. Def::Fn(def_id) | Def::Const(def_id) | Def::Static(def_id, _) => { path_segs.push(PathSeg(def_id, last)); } - // Case 3. Reference to a method or associated const. + // Case 4. Reference to a method or associated const. Def::Method(def_id) | Def::AssociatedConst(def_id) => { if segments.len() >= 2 { @@ -5122,7 +5162,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { path_segs.push(PathSeg(def_id, last)); } - // Case 4. Local variable, no generics. + // Case 5. Local variable, no generics. Def::Local(..) | Def::Upvar(..) => {} _ => bug!("unexpected definition: {:?}", def), @@ -5150,7 +5190,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { node_id, ); - let path_segs = self.def_ids_for_path_segments(segments, def); + let path_segs = self.def_ids_for_path_segments(segments, self_ty, def); let mut user_self_ty = None; match def { @@ -5185,10 +5225,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let generic_segs = path_segs.iter().map(|PathSeg(_, index)| index) - .collect::<FxHashSet<_>>(); + let is_alias_variant_ctor = if tcx.features().type_alias_enum_variants { + match def { + Def::VariantCtor(_, _) if self_ty.is_some() => true, + _ => false, + }; + } else { + false + }; + + let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { - if !generic_segs.contains(&index) { + if !generic_segs.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None @@ -5272,6 +5320,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } + Def::VariantCtor(_, _) if self_ty.is_some() => { + let def_id = def.def_id(); + + let ty = self.tcx.type_of(def_id); + if tcx.features().type_alias_enum_variants { + if let Some(self_ty) = self_ty { + match ty.ty_adt_def() { + Some(adt_def) if adt_def.is_enum() => { + return (self_ty, def); + } + _ => {} + } + } + } + (def_id, ty) + } _ => { let def_id = def.def_id(); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index cba07ab3602c5..d63e5a3fe93a4 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -105,12 +105,14 @@ mod outlives; mod variance; use hir::Node; +use hir::def::Def; use rustc_target::spec::abi::Abi; use rustc::hir; use rustc::infer::InferOk; use rustc::lint; use rustc::middle; use rustc::session; +use rustc::session::config::nightly_options; use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; @@ -129,6 +131,30 @@ pub struct TypeAndSubsts<'tcx> { ty: Ty<'tcx>, } +fn allow_type_alias_enum_variants<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + ty_hir: &hir::Ty, + span: Span) -> bool { + let allow_feature = tcx.features().type_alias_enum_variants; + if !allow_feature { + // Only print error if we know the type is an alias. + if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ty_hir.node { + if let Def::TyAlias(_) = path.def { + let mut err = tcx.sess.struct_span_err( + span, + "type alias enum variants are not yet allowed" + ); + if nightly_options::is_nightly_build() { + help!(&mut err, + "add `#![feature(type_alias_enum_variants)]` to the \ + crate attributes to enable"); + } + err.emit(); + } + } + } + allow_feature +} + fn require_c_abi_if_variadic(tcx: TyCtxt, decl: &hir::FnDecl, abi: Abi, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 70df403d0c2ea..0eeef969e3524 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -471,11 +471,14 @@ declare_features! ( // Allows `const _: TYPE = VALUE`. (active, underscore_const_names, "1.31.0", Some(54912), None), - // `reason = ` in lint attributes and `expect` lint attribute + // Adds `reason` and `expect` lint attributes. (active, lint_reasons, "1.31.0", Some(54503), None), // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`. (active, extern_crate_self, "1.31.0", Some(56409), None), + + // Allows paths to enum variants on type aliases. + (active, type_alias_enum_variants, "1.31.0", Some(49683), None), ); declare_features! ( From 711af86b0ebcc76e47480831207f00484fcf6225 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Mon, 3 Dec 2018 00:56:08 +0000 Subject: [PATCH 009/124] Added tests for feature. --- src/test/run-pass/type-alias-enum-variants.rs | 30 ++++++++ .../feature-gate-type_alias_enum_variants.rs | 25 +++++++ ...ature-gate-type_alias_enum_variants.stderr | 72 +++++++++++++++++++ src/test/ui/type-alias-enum-variants.rs | 10 +++ src/test/ui/type-alias-enum-variants.stderr | 9 +++ 5 files changed, 146 insertions(+) create mode 100644 src/test/run-pass/type-alias-enum-variants.rs create mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs create mode 100644 src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr create mode 100644 src/test/ui/type-alias-enum-variants.rs create mode 100644 src/test/ui/type-alias-enum-variants.stderr diff --git a/src/test/run-pass/type-alias-enum-variants.rs b/src/test/run-pass/type-alias-enum-variants.rs new file mode 100644 index 0000000000000..0cf413babcbf6 --- /dev/null +++ b/src/test/run-pass/type-alias-enum-variants.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_enum_variants)] + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type FooAlias = Foo; +type OptionAlias = Option<i32>; + +impl Foo { + fn foo() -> Self { + Self::Bar(3) + } +} + +fn main() { + let t = FooAlias::Bar(1); + assert_eq!(t, Foo::Bar(1)); + let t = FooAlias::Baz { i: 2 }; + assert_eq!(t, Foo::Baz { i: 2 }); + match t { + FooAlias::Bar(_i) => {} + FooAlias::Baz { i } => { assert_eq!(i, 2); } + } + assert_eq!(Foo::foo(), Foo::Bar(3)); + + assert_eq!(OptionAlias::Some(4), Option::Some(4)); +} diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs new file mode 100644 index 0000000000000..39472af43fdb2 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type Alias = Foo; + +fn main() { + let t = Alias::Bar(0); + let t = Alias::Baz { i: 0 }; + match t { + Alias::Bar(_i) => {} + Alias::Baz { i: _i } => {} + } +} diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr new file mode 100644 index 0000000000000..7dce09e483f9d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr @@ -0,0 +1,72 @@ +error: type alias enum variants are not yet allowed + --> $DIR/feature-gate-type_alias_enum_variants.rs:19:13 + | +LL | let t = Alias::Bar(0); + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error[E0599]: no variant named `Bar` found for type `Foo` in the current scope + --> $DIR/feature-gate-type_alias_enum_variants.rs:19:20 + | +LL | enum Foo { + | -------- variant `Bar` not found here +... +LL | let t = Alias::Bar(0); + | -------^^^ + | | + | variant not found in `Foo` + | + = help: did you mean `Bar`? + +error: type alias enum variants are not yet allowed + --> $DIR/feature-gate-type_alias_enum_variants.rs:20:13 + | +LL | let t = Alias::Baz { i: 0 }; + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error[E0223]: ambiguous associated type + --> $DIR/feature-gate-type_alias_enum_variants.rs:20:13 + | +LL | let t = Alias::Baz { i: 0 }; + | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` + +error: type alias enum variants are not yet allowed + --> $DIR/feature-gate-type_alias_enum_variants.rs:22:9 + | +LL | Alias::Bar(_i) => {} + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error[E0599]: no variant named `Bar` found for type `Foo` in the current scope + --> $DIR/feature-gate-type_alias_enum_variants.rs:22:16 + | +LL | enum Foo { + | -------- variant `Bar` not found here +... +LL | Alias::Bar(_i) => {} + | -------^^^---- variant not found in `Foo` + | + = help: did you mean `Bar`? + +error: type alias enum variants are not yet allowed + --> $DIR/feature-gate-type_alias_enum_variants.rs:23:9 + | +LL | Alias::Baz { i: _i } => {} + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error[E0223]: ambiguous associated type + --> $DIR/feature-gate-type_alias_enum_variants.rs:23:9 + | +LL | Alias::Baz { i: _i } => {} + | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` + +error: aborting due to 8 previous errors + +Some errors occurred: E0223, E0599. +For more information about an error, try `rustc --explain E0223`. diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs new file mode 100644 index 0000000000000..8e5aaae0a9323 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_enum_variants)] + +type Alias<T> = Option<T>; + +fn main() { + let _ = Option::<u8>::None; // OK + let _ = Option::None::<u8>; // OK (Lint in future!) + let _ = Alias::<u8>::None; // OK + let _ = Alias::None::<u8>; // Error +} diff --git a/src/test/ui/type-alias-enum-variants.stderr b/src/test/ui/type-alias-enum-variants.stderr new file mode 100644 index 0000000000000..e7003217c8d7c --- /dev/null +++ b/src/test/ui/type-alias-enum-variants.stderr @@ -0,0 +1,9 @@ +error[E0109]: type parameters are not allowed on this type + --> $DIR/type-alias-enum-variants.rs:9:27 + | +LL | let _ = Alias::None::<u8>; // Error + | ^^ type parameter not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. From 9fcbf24f30d30d8b276e1af6c44ff629c8222317 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Mon, 3 Dec 2018 00:56:47 +0000 Subject: [PATCH 010/124] Made suggestion diagnostics more consistent for enum variant names, relative to method names. --- src/librustc_typeck/astconv.rs | 12 ++-- src/librustc_typeck/check/method/mod.rs | 14 ++--- src/librustc_typeck/check/method/suggest.rs | 70 ++++++++++++--------- src/librustc_typeck/check/mod.rs | 53 +++++++++------- src/librustc_typeck/lib.rs | 4 +- 5 files changed, 84 insertions(+), 69 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 18c19352a603b..67f330536b85e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1277,7 +1277,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ref_id: ast::NodeId, span: Span, ty: Ty<'tcx>, - ty_hir: &hir::Ty, + qself: &hir::Ty, ty_path_def: Def, item_segment: &hir::PathSegment) -> (Ty<'tcx>, Def) @@ -1292,11 +1292,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // Check if we have an enum variant here. if let ty::Adt(adt_def, _) = ty.sty { if adt_def.is_enum() { - if allow_type_alias_enum_variants(tcx, ty_hir, span) { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + if allow_type_alias_enum_variants(tcx, qself, span) { let def = Def::Variant(variant_def.did); return (ty, def); } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f594690f77f02..4c96d476caa22 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -8,7 +8,7 @@ mod suggest; pub use self::MethodError::*; pub use self::CandidateSource::*; -pub use self::suggest::TraitInfo; +pub use self::suggest::{SelfSource, TraitInfo}; use check::FnCtxt; use namespace::Namespace; @@ -361,7 +361,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, method_name: ast::Ident, self_ty: Ty<'tcx>, - self_ty_hir: &hir::Ty, + qself: &hir::Ty, expr_id: ast::NodeId) -> Result<Def, MethodError<'tcx>> { debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", @@ -375,11 +375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check if we have an enum variant here. if let ty::Adt(adt_def, _) = self_ty.sty { if adt_def.is_enum() { - if allow_type_alias_enum_variants(tcx, self_ty_hir, span) { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(method_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + if allow_type_alias_enum_variants(tcx, qself, span) { let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); return Ok(def); } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 65a58d345ccfa..b368250b32d97 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -6,7 +6,7 @@ use errors::{Applicability, DiagnosticBuilder}; use middle::lang_items::FnOnceTraitLangItem; use namespace::Namespace; use rustc_data_structures::sync::Lrc; -use rustc::hir::{self, Node}; +use rustc::hir::{self, ExprKind, Node, QPath}; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::hir::map as hir_map; @@ -60,13 +60,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn report_method_error(&self, - span: Span, - rcvr_ty: Ty<'tcx>, - item_name: ast::Ident, - rcvr_expr: Option<&hir::Expr>, - error: MethodError<'tcx>, - args: Option<&'gcx [hir::Expr]>) { + pub fn report_method_error<'b>(&self, + span: Span, + rcvr_ty: Ty<'tcx>, + item_name: ast::Ident, + source: SelfSource<'b>, + error: MethodError<'tcx>, + args: Option<&'gcx [hir::Expr]>) { // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return; @@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .filter_map(|info| self.associated_item(info.def_id, item_name, Namespace::Value) ); - if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(), - actual.has_concrete_skeleton(), - rcvr_expr, - candidates.next()) { + if let (true, false, SelfSource::MethodCall(expr), Some(_)) = + (actual.is_numeric(), + actual.has_concrete_skeleton(), + source, + candidates.next()) { let mut err = struct_span_err!( tcx.sess, span, @@ -231,7 +232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "f32" }; match expr.node { - hir::ExprKind::Lit(ref lit) => { + ExprKind::Lit(ref lit) => { // numeric literal let snippet = tcx.sess.source_map().span_to_snippet(lit.span) .unwrap_or_else(|_| "<numeric literal>".to_owned()); @@ -247,9 +248,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MaybeIncorrect, ); } - hir::ExprKind::Path(ref qpath) => { + ExprKind::Path(ref qpath) => { // local binding - if let &hir::QPath::Resolved(_, ref path) = &qpath { + if let &QPath::Resolved(_, ref path) = &qpath { if let hir::def::Def::Local(node_id) = path.def { let span = tcx.hir().span(node_id); let snippet = tcx.sess.source_map().span_to_snippet(span) @@ -294,7 +295,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { let mut err = struct_span_err!( tcx.sess, - span, + item_name.span, E0599, "no {} named `{}` found for type `{}` in the current scope", item_kind, @@ -302,7 +303,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_str ); if let Some(suggestion) = suggestion { - err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion)); + // enum variant + err.help(&format!("did you mean `{}`?", suggestion)); } err } @@ -326,7 +328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { for (ty, _) in self.autoderef(span, rcvr_ty) { if let ty::Adt(def, substs) = ty.sty { if !def.is_enum() { @@ -377,10 +379,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) { report_function!(expr.span, expr_string); - } else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = + } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.node { if let Some(segment) = path.segments.last() { @@ -396,7 +398,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(span, "this is an associated function, not a method"); } if static_sources.len() == 1 { - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { err.span_suggestion_with_applicability(expr.span.to(span), "use associated function syntax instead", format!("{}::{}", @@ -433,7 +435,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span, rcvr_ty, item_name, - rcvr_expr, + source, out_of_scope_traits); } @@ -571,18 +573,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - fn suggest_traits_to_import(&self, - err: &mut DiagnosticBuilder, - span: Span, - rcvr_ty: Ty<'tcx>, - item_name: ast::Ident, - rcvr_expr: Option<&hir::Expr>, - valid_out_of_scope_traits: Vec<DefId>) { + fn suggest_traits_to_import<'b>(&self, + err: &mut DiagnosticBuilder, + span: Span, + rcvr_ty: Ty<'tcx>, + item_name: ast::Ident, + source: SelfSource<'b>, + valid_out_of_scope_traits: Vec<DefId>) { if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } - let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr); + let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source); // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are @@ -663,7 +665,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This occurs for UFCS desugaring of `T::method`, where there is no // receiver expression for the method call, and thus no autoderef. - if rcvr_expr.is_none() { + if let SelfSource::QPath(_) = source { return is_local(self.resolve_type_vars_with_obligations(rcvr_ty)); } @@ -671,6 +673,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } +#[derive(Copy, Clone)] +pub enum SelfSource<'a> { + QPath(&'a hir::Ty), + MethodCall(&'a hir::Expr /* rcvr */), +} + #[derive(Copy, Clone)] pub struct TraitInfo { pub def_id: DefId, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 686365648f00d..7e8c55a1f5601 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -142,7 +142,7 @@ use self::autoderef::Autoderef; use self::callee::DeferredCallResolution; use self::coercion::{CoerceMany, DynamicCoerceMany}; pub use self::compare_method::{compare_impl_method, compare_const_impl}; -use self::method::MethodCallee; +use self::method::{MethodCallee, SelfSource}; use self::TupleArgumentsFlag::*; /// The type of a local binding, including the revealed type for anon types. @@ -3244,7 +3244,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.report_method_error(span, rcvr_t, segment.ident, - Some(rcvr), + SelfSource::MethodCall(rcvr), error, Some(args)); } @@ -4561,7 +4561,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) { - let (ty, ty_hir, item_segment) = match *qpath { + let (ty, qself, item_segment) = match *qpath { hir::QPath::Resolved(ref opt_qself, ref path) => { return (path.def, opt_qself.as_ref().map(|qself| self.to_ty(qself)), @@ -4578,7 +4578,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return (*cached_def, Some(ty), slice::from_ref(&**item_segment)) } let item_name = item_segment.ident; - let def = match self.resolve_ufcs(span, item_name, ty, ty_hir, node_id) { + let def = match self.resolve_ufcs(span, item_name, ty, qself, node_id) { Ok(def) => def, Err(error) => { let def = match error { @@ -4586,7 +4586,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => Def::Err, }; if item_name.name != keywords::Invalid.name() { - self.report_method_error(span, ty, item_name, None, error, None); + self.report_method_error(span, + ty, + item_name, + SelfSource::QPath(qself), + error, + None); } def } @@ -5112,7 +5117,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Case 2. Reference to a variant constructor. Def::VariantCtor(def_id, ..) => { - if tcx.features().type_alias_enum_variants { + if self.tcx.features().type_alias_enum_variants { let adt_def = self_ty.and_then(|t| t.ty_adt_def()); let (generics_def_id, index) = if let Some(adt_def) = adt_def { debug_assert!(adt_def.is_enum()); @@ -5190,16 +5195,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { node_id, ); + let tcx = self.tcx; + let path_segs = self.def_ids_for_path_segments(segments, self_ty, def); let mut user_self_ty = None; match def { Def::Method(def_id) | Def::AssociatedConst(def_id) => { - let container = self.tcx.associated_item(def_id).container; + let container = tcx.associated_item(def_id).container; match container { ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(self.tcx, span, trait_did) + callee::check_legal_trait_for_method_call(tcx, span, trait_did) } ty::ImplContainer(impl_def_id) => { if segments.len() == 1 { @@ -5229,7 +5236,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match def { Def::VariantCtor(_, _) if self_ty.is_some() => true, _ => false, - }; + } } else { false }; @@ -5247,7 +5254,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Local(nid) | Def::Upvar(nid, ..) => { let ty = self.local_ty(span, nid).decl_ty; let ty = self.normalize_associated_types_in(span, &ty); - self.write_ty(self.tcx.hir().node_to_hir_id(node_id), ty); + self.write_ty(tcx.hir().node_to_hir_id(node_id), ty); return (ty, def); } _ => {} @@ -5263,13 +5270,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut infer_args_for_err = FxHashSet::default(); for &PathSeg(def_id, index) in &path_segs { let seg = &segments[index]; - let generics = self.tcx.generics_of(def_id); + let generics = tcx.generics_of(def_id); // Argument-position `impl Trait` is treated as a normal generic // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. let suppress_errors = AstConv::check_generic_arg_count_for_call( - self.tcx, + tcx, span, &generics, &seg, @@ -5282,7 +5289,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let has_self = path_segs.last().map(|PathSeg(def_id, _)| { - self.tcx.generics_of(*def_id).has_self + tcx.generics_of(*def_id).has_self }).unwrap_or(false); let mut new_def = def; @@ -5295,10 +5302,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); new_def = Def::StructCtor(variant.did, variant.ctor_kind); - (variant.did, self.tcx.type_of(variant.did)) + (variant.did, tcx.type_of(variant.did)) } _ => { - let mut err = self.tcx.sess.struct_span_err(span, + let mut err = tcx.sess.struct_span_err(span, "the `Self` constructor can only be used with tuple or unit structs"); if let Some(adt_def) = adt_def { match adt_def.adt_kind() { @@ -5316,14 +5323,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } err.emit(); - (impl_def_id, self.tcx.types.err) + (impl_def_id, tcx.types.err) } } } Def::VariantCtor(_, _) if self_ty.is_some() => { let def_id = def.def_id(); - let ty = self.tcx.type_of(def_id); + let ty = tcx.type_of(def_id); if tcx.features().type_alias_enum_variants { if let Some(self_ty) = self_ty { match ty.ty_adt_def() { @@ -5341,13 +5348,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. - let ty = self.tcx.type_of(def_id); + let ty = tcx.type_of(def_id); (def_id, ty) } }; let substs = AstConv::create_substs_for_generic_args( - self.tcx, + tcx, def_id, &[][..], has_self, @@ -5393,10 +5400,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If we have a default, then we it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. - let default = self.tcx.type_of(param.def_id); + let default = tcx.type_of(param.def_id); self.normalize_ty( span, - default.subst_spanned(self.tcx, substs.unwrap(), Some(span)) + default.subst_spanned(tcx, substs.unwrap(), Some(span)) ).into() } else { // If no type arguments were provided, we have to infer them. @@ -5413,7 +5420,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!ty.has_escaping_bound_vars()); // First, store the "user substs" for later. - let hir_id = self.tcx.hir().node_to_hir_id(node_id); + let hir_id = tcx.hir().node_to_hir_id(node_id); self.write_user_substs_from_substs(hir_id, substs, user_self_ty); // Add all the obligations that are required, substituting and @@ -5432,7 +5439,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // is inherent, there is no `Self` parameter, instead, the impl needs // type parameters, which we can infer by unifying the provided `Self` // with the substituted impl type. - let ty = self.tcx.type_of(impl_def_id); + let ty = tcx.type_of(impl_def_id); let impl_ty = self.instantiate_type_scheme(span, &substs, &ty); match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index d63e5a3fe93a4..4950ea319271b 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -132,12 +132,12 @@ pub struct TypeAndSubsts<'tcx> { } fn allow_type_alias_enum_variants<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty_hir: &hir::Ty, + qself: &hir::Ty, span: Span) -> bool { let allow_feature = tcx.features().type_alias_enum_variants; if !allow_feature { // Only print error if we know the type is an alias. - if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ty_hir.node { + if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = qself.node { if let Def::TyAlias(_) = path.def { let mut err = tcx.sess.struct_span_err( span, From 4137376617fc42b09da68c9ae4c1459607b9b10d Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Thu, 6 Dec 2018 01:02:21 +0000 Subject: [PATCH 011/124] Fixed tests. --- src/librustc_typeck/lib.rs | 2 +- .../feature-gate-type_alias_enum_variants.rs | 8 ++++++++ ...ature-gate-type_alias_enum_variants.stderr | 20 +++++++++---------- src/test/ui/type-alias-enum-variants.rs | 1 + 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4950ea319271b..8c0913a56b514 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -141,7 +141,7 @@ fn allow_type_alias_enum_variants<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, if let Def::TyAlias(_) = path.def { let mut err = tcx.sess.struct_span_err( span, - "type alias enum variants are not yet allowed" + "enum variants on type aliases are experimental" ); if nightly_options::is_nightly_build() { help!(&mut err, diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs index 39472af43fdb2..2dcd0dcd24381 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs @@ -17,9 +17,17 @@ type Alias = Foo; fn main() { let t = Alias::Bar(0); + //~^ ERROR enum variants on type aliases are experimental + //~^^ ERROR no variant named `Bar` found for type `Foo` in the current scope let t = Alias::Baz { i: 0 }; + //~^ ERROR enum variants on type aliases are experimental + //~^^ ERROR ambiguous associated type match t { Alias::Bar(_i) => {} + //~^ ERROR enum variants on type aliases are experimental + //~^^ ERROR no variant named `Bar` found for type `Foo` in the current scope Alias::Baz { i: _i } => {} + //~^ ERROR enum variants on type aliases are experimental + //~^^ ERROR ambiguous associated type } } diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr index 7dce09e483f9d..7a49770d97a2f 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr @@ -1,4 +1,4 @@ -error: type alias enum variants are not yet allowed +error: enum variants on type aliases are experimental --> $DIR/feature-gate-type_alias_enum_variants.rs:19:13 | LL | let t = Alias::Bar(0); @@ -19,8 +19,8 @@ LL | let t = Alias::Bar(0); | = help: did you mean `Bar`? -error: type alias enum variants are not yet allowed - --> $DIR/feature-gate-type_alias_enum_variants.rs:20:13 +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:22:13 | LL | let t = Alias::Baz { i: 0 }; | ^^^^^^^^^^ @@ -28,13 +28,13 @@ LL | let t = Alias::Baz { i: 0 }; = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable error[E0223]: ambiguous associated type - --> $DIR/feature-gate-type_alias_enum_variants.rs:20:13 + --> $DIR/feature-gate-type_alias_enum_variants.rs:22:13 | LL | let t = Alias::Baz { i: 0 }; | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` -error: type alias enum variants are not yet allowed - --> $DIR/feature-gate-type_alias_enum_variants.rs:22:9 +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:26:9 | LL | Alias::Bar(_i) => {} | ^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | Alias::Bar(_i) => {} = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable error[E0599]: no variant named `Bar` found for type `Foo` in the current scope - --> $DIR/feature-gate-type_alias_enum_variants.rs:22:16 + --> $DIR/feature-gate-type_alias_enum_variants.rs:26:16 | LL | enum Foo { | -------- variant `Bar` not found here @@ -52,8 +52,8 @@ LL | Alias::Bar(_i) => {} | = help: did you mean `Bar`? -error: type alias enum variants are not yet allowed - --> $DIR/feature-gate-type_alias_enum_variants.rs:23:9 +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:29:9 | LL | Alias::Baz { i: _i } => {} | ^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | Alias::Baz { i: _i } => {} = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable error[E0223]: ambiguous associated type - --> $DIR/feature-gate-type_alias_enum_variants.rs:23:9 + --> $DIR/feature-gate-type_alias_enum_variants.rs:29:9 | LL | Alias::Baz { i: _i } => {} | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs index 8e5aaae0a9323..73395e6a9798a 100644 --- a/src/test/ui/type-alias-enum-variants.rs +++ b/src/test/ui/type-alias-enum-variants.rs @@ -7,4 +7,5 @@ fn main() { let _ = Option::None::<u8>; // OK (Lint in future!) let _ = Alias::<u8>::None; // OK let _ = Alias::None::<u8>; // Error + //~^ type parameters are not allowed on this type } From c85edb8ebf195361651774b24fbd989a2be6631e Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Fri, 7 Dec 2018 18:15:36 +0000 Subject: [PATCH 012/124] Fixed more tests. --- .../associated-const-no-item.stderr | 6 +++-- src/test/ui/bogus-tag.rs | 6 ++--- src/test/ui/bogus-tag.stderr | 6 ++--- src/test/ui/did_you_mean/bad-assoc-pat.stderr | 24 ++++++++++++------- .../dont-suggest-private-trait-method.stderr | 6 +++-- .../ui/empty/empty-struct-braces-expr.stderr | 16 ++++++++----- src/test/ui/error-codes/E0599.stderr | 4 ++-- .../ui/invalid/invalid-path-in-const.stderr | 6 +++-- src/test/ui/issues/issue-22933-2.stderr | 6 +++-- src/test/ui/issues/issue-22933-3.stderr | 6 +++-- src/test/ui/issues/issue-23173.stderr | 24 ++++++++++++------- src/test/ui/issues/issue-23217.stderr | 8 ++++--- src/test/ui/issues/issue-28344.stderr | 12 ++++++---- src/test/ui/issues/issue-28586.stderr | 6 +++-- src/test/ui/issues/issue-28971.stderr | 6 ++--- src/test/ui/issues/issue-30123.stderr | 6 +++-- src/test/ui/issues/issue-38919.stderr | 6 +++-- src/test/ui/issues/issue-39559.stderr | 6 +++-- src/test/ui/issues/issue-3973.stderr | 6 +++-- src/test/ui/issues/issue-42880.stderr | 4 ++-- src/test/ui/issues/issue-7950.stderr | 6 +++-- src/test/ui/lexical-scopes.stderr | 6 +++-- .../no-double-error.stderr | 6 +++-- .../rust-2018/trait-import-suggestions.stderr | 6 +++-- src/test/ui/traits/trait-item-privacy.stderr | 24 ++++++++++++------- .../ui/ufcs/ufcs-partially-resolved.stderr | 12 ++++++---- .../ui/unspecified-self-in-trait-ref.stderr | 24 ++++++++++++------- 27 files changed, 164 insertions(+), 90 deletions(-) diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index cd60132efdd65..de172049872f5 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope - --> $DIR/associated-const-no-item.rs:5:16 + --> $DIR/associated-const-no-item.rs:5:23 | LL | const X: i32 = <i32>::ID; - | ^^^^^^^^^ associated item not found in `i32` + | -------^^ + | | + | associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `ID`, perhaps you need to implement it: diff --git a/src/test/ui/bogus-tag.rs b/src/test/ui/bogus-tag.rs index ca8db9b502b5b..c594385eec2d6 100644 --- a/src/test/ui/bogus-tag.rs +++ b/src/test/ui/bogus-tag.rs @@ -3,8 +3,8 @@ enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } fn main() { let red: Color = Color::Rgb(255, 0, 0); match red { - Color::Rgb(r, g, b) => { println!("rgb"); } - Color::Hsl(h, s, l) => { println!("hsl"); } - //~^ ERROR no variant + Color::Rgb(r, g, b) => { println!("rgb"); } + Color::Hsl(h, s, l) => { println!("hsl"); } + //~^ ERROR no variant } } diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index 1225abd2c8a16..1cb5ee9b6305c 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -1,11 +1,11 @@ error[E0599]: no variant named `Hsl` found for type `Color` in the current scope - --> $DIR/bogus-tag.rs:7:7 + --> $DIR/bogus-tag.rs:7:9 | LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } | ---------- variant `Hsl` not found here ... -LL | Color::Hsl(h, s, l) => { println!("hsl"); } - | ^^^^^^^^^^^^^^^^^^^ variant not found in `Color` +LL | Color::Hsl(h, s, l) => { println!("hsl"); } + | ^^^^^^^^^^^^^^^^^^^ variant not found in `Color` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr index 86beb0f33f64a..92fd9f26777f1 100644 --- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr @@ -23,28 +23,36 @@ LL | &(u8,)::AssocItem => {} | ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem` error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope - --> $DIR/bad-assoc-pat.rs:3:9 + --> $DIR/bad-assoc-pat.rs:3:15 | LL | [u8]::AssocItem => {} - | ^^^^^^^^^^^^^^^ associated item not found in `[u8]` + | ------^^^^^^^^^ + | | + | associated item not found in `[u8]` error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope - --> $DIR/bad-assoc-pat.rs:6:9 + --> $DIR/bad-assoc-pat.rs:6:19 | LL | (u8, u8)::AssocItem => {} - | ^^^^^^^^^^^^^^^^^^^ associated item not found in `(u8, u8)` + | ----------^^^^^^^^^ + | | + | associated item not found in `(u8, u8)` error[E0599]: no associated item named `AssocItem` found for type `_` in the current scope - --> $DIR/bad-assoc-pat.rs:9:9 + --> $DIR/bad-assoc-pat.rs:9:12 | LL | _::AssocItem => {} - | ^^^^^^^^^^^^ associated item not found in `_` + | ---^^^^^^^^^ + | | + | associated item not found in `_` error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope - --> $DIR/bad-assoc-pat.rs:14:10 + --> $DIR/bad-assoc-pat.rs:14:17 | LL | &(u8,)::AssocItem => {} - | ^^^^^^^^^^^^^^^^ associated item not found in `(u8,)` + | -------^^^^^^^^^ + | | + | associated item not found in `(u8,)` error: aborting due to 8 previous errors diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr index 483192149b850..af4253779a4f5 100644 --- a/src/test/ui/dont-suggest-private-trait-method.stderr +++ b/src/test/ui/dont-suggest-private-trait-method.stderr @@ -1,11 +1,13 @@ error[E0599]: no function or associated item named `new` found for type `T` in the current scope - --> $DIR/dont-suggest-private-trait-method.rs:4:5 + --> $DIR/dont-suggest-private-trait-method.rs:4:8 | LL | struct T; | --------- function or associated item `new` not found for this ... LL | T::new(); - | ^^^^^^ function or associated item not found in `T` + | ---^^^ + | | + | function or associated item not found in `T` error: aborting due to previous error diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index be613121fe88e..d3e1cebd26fe1 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -47,20 +47,24 @@ LL | let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1 | did you mean `XEmpty1 { /* fields */ }`? error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope - --> $DIR/empty-struct-braces-expr.rs:22:15 + --> $DIR/empty-struct-braces-expr.rs:22:19 | LL | let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type - | ^^^^^^^^^^ variant not found in `empty_struct::XE` + | ----^^^^^^ + | | + | variant not found in `empty_struct::XE` | - = note: did you mean `empty_struct::XE::XEmpty3`? + = help: did you mean `XEmpty3`? error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope - --> $DIR/empty-struct-braces-expr.rs:23:15 + --> $DIR/empty-struct-braces-expr.rs:23:19 | LL | let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type - | ^^^^^^^^^^ variant not found in `empty_struct::XE` + | ----^^^^^^ + | | + | variant not found in `empty_struct::XE` | - = note: did you mean `empty_struct::XE::XEmpty3`? + = help: did you mean `XEmpty3`? error: aborting due to 8 previous errors diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr index 5a7cddbf38210..85110889e9a7b 100644 --- a/src/test/ui/error-codes/E0599.stderr +++ b/src/test/ui/error-codes/E0599.stderr @@ -1,11 +1,11 @@ error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope - --> $DIR/E0599.rs:4:15 + --> $DIR/E0599.rs:4:20 | LL | struct Foo; | ----------- associated item `NotEvenReal` not found for this ... LL | || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 - | ^^^^^^^^^^^^^^^^^^ associated item not found in `Foo` + | -----^^^^^^^^^^^-- associated item not found in `Foo` error: aborting due to previous error diff --git a/src/test/ui/invalid/invalid-path-in-const.stderr b/src/test/ui/invalid/invalid-path-in-const.stderr index 6541c92c691c8..13176b8b8fb15 100644 --- a/src/test/ui/invalid/invalid-path-in-const.stderr +++ b/src/test/ui/invalid/invalid-path-in-const.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `DOESNOTEXIST` found for type `u32` in the current scope - --> $DIR/invalid-path-in-const.rs:2:18 + --> $DIR/invalid-path-in-const.rs:2:23 | LL | fn f(a: [u8; u32::DOESNOTEXIST]) {} - | ^^^^^^^^^^^^^^^^^ associated item not found in `u32` + | -----^^^^^^^^^^^^ + | | + | associated item not found in `u32` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr index 58145a38026e4..97962adc2d286 100644 --- a/src/test/ui/issues/issue-22933-2.stderr +++ b/src/test/ui/issues/issue-22933-2.stderr @@ -1,11 +1,13 @@ error[E0599]: no variant named `PIE` found for type `Delicious` in the current scope - --> $DIR/issue-22933-2.rs:4:44 + --> $DIR/issue-22933-2.rs:4:55 | LL | enum Delicious { | -------------- variant `PIE` not found here ... LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, - | ^^^^^^^^^^^^^^ variant not found in `Delicious` + | -----------^^^ + | | + | variant not found in `Delicious` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22933-3.stderr b/src/test/ui/issues/issue-22933-3.stderr index 2ca1bd7401a20..aa0052f97013e 100644 --- a/src/test/ui/issues/issue-22933-3.stderr +++ b/src/test/ui/issues/issue-22933-3.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `MIN` found for type `u8` in the current scope - --> $DIR/issue-22933-3.rs:1:18 + --> $DIR/issue-22933-3.rs:1:22 | LL | const FOO: [u32; u8::MIN as usize] = []; - | ^^^^^^^ associated item not found in `u8` + | ----^^^ + | | + | associated item not found in `u8` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr index de4c8422b9ccb..98c4f867ad6a0 100644 --- a/src/test/ui/issues/issue-23173.stderr +++ b/src/test/ui/issues/issue-23173.stderr @@ -1,38 +1,46 @@ error[E0599]: no variant named `Homura` found for type `Token` in the current scope - --> $DIR/issue-23173.rs:9:16 + --> $DIR/issue-23173.rs:9:23 | LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } | ---------- variant `Homura` not found here ... LL | use_token(&Token::Homura); - | ^^^^^^^^^^^^^ variant not found in `Token` + | -------^^^^^^ + | | + | variant not found in `Token` error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:11:5 + --> $DIR/issue-23173.rs:11:13 | LL | struct Struct { | ------------- function or associated item `method` not found for this ... LL | Struct::method(); - | ^^^^^^^^^^^^^^ function or associated item not found in `Struct` + | --------^^^^^^ + | | + | function or associated item not found in `Struct` error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:13:5 + --> $DIR/issue-23173.rs:13:13 | LL | struct Struct { | ------------- function or associated item `method` not found for this ... LL | Struct::method; - | ^^^^^^^^^^^^^^ function or associated item not found in `Struct` + | --------^^^^^^ + | | + | function or associated item not found in `Struct` error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:15:5 + --> $DIR/issue-23173.rs:15:13 | LL | struct Struct { | ------------- associated item `Assoc` not found for this ... LL | Struct::Assoc; - | ^^^^^^^^^^^^^ associated item not found in `Struct` + | --------^^^^^ + | | + | associated item not found in `Struct` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr index a058caf81bbe8..208d0cc499a80 100644 --- a/src/test/ui/issues/issue-23217.stderr +++ b/src/test/ui/issues/issue-23217.stderr @@ -1,12 +1,14 @@ error[E0599]: no variant named `A` found for type `SomeEnum` in the current scope - --> $DIR/issue-23217.rs:2:9 + --> $DIR/issue-23217.rs:2:19 | LL | pub enum SomeEnum { | ----------------- variant `A` not found here LL | B = SomeEnum::A, - | ^^^^^^^^^^^ variant not found in `SomeEnum` + | ----------^ + | | + | variant not found in `SomeEnum` | - = note: did you mean `SomeEnum::B`? + = help: did you mean `B`? error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index f7d8d2af86208..146ebad6ce175 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -5,10 +5,12 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^^^^^^^^ associated type `Output` must be specified error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:4:17 + --> $DIR/issue-28344.rs:4:25 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^^^^^^^^^ function or associated item not found in `dyn std::ops::BitXor<_>` + | --------^^^^^ + | | + | function or associated item not found in `dyn std::ops::BitXor<_>` | = help: did you mean `bitxor`? @@ -19,10 +21,12 @@ LL | let g = BitXor::bitor; | ^^^^^^^^^^^^^ associated type `Output` must be specified error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:8:13 + --> $DIR/issue-28344.rs:8:21 | LL | let g = BitXor::bitor; - | ^^^^^^^^^^^^^ function or associated item not found in `dyn std::ops::BitXor<_>` + | --------^^^^^ + | | + | function or associated item not found in `dyn std::ops::BitXor<_>` | = help: did you mean `bitxor`? diff --git a/src/test/ui/issues/issue-28586.stderr b/src/test/ui/issues/issue-28586.stderr index 52af2f54653f3..eccb474c15eb6 100644 --- a/src/test/ui/issues/issue-28586.stderr +++ b/src/test/ui/issues/issue-28586.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `BYTES` found for type `usize` in the current scope - --> $DIR/issue-28586.rs:4:19 + --> $DIR/issue-28586.rs:4:26 | LL | impl Foo for [u8; usize::BYTES] {} - | ^^^^^^^^^^^^ associated item not found in `usize` + | -------^^^^^ + | | + | associated item not found in `usize` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr index f6362faab12b8..d5dbd5f64885c 100644 --- a/src/test/ui/issues/issue-28971.stderr +++ b/src/test/ui/issues/issue-28971.stderr @@ -1,13 +1,13 @@ error[E0599]: no variant named `Baz` found for type `Foo` in the current scope - --> $DIR/issue-28971.rs:9:13 + --> $DIR/issue-28971.rs:9:18 | LL | enum Foo { | -------- variant `Baz` not found here ... LL | Foo::Baz(..) => (), - | ^^^^^^^^^^^^ variant not found in `Foo` + | -----^^^---- variant not found in `Foo` | - = note: did you mean `Foo::Bar`? + = help: did you mean `Bar`? error: aborting due to previous error diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr index 9729b13d57fe8..555bdb1236fe6 100644 --- a/src/test/ui/issues/issue-30123.stderr +++ b/src/test/ui/issues/issue-30123.stderr @@ -1,8 +1,10 @@ error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope - --> $DIR/issue-30123.rs:7:14 + --> $DIR/issue-30123.rs:7:33 | LL | let ug = Graph::<i32, i32>::new_undirected(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>` + | -------------------^^^^^^^^^^^^^^ + | | + | function or associated item not found in `issue_30123_aux::Graph<i32, i32>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr index 41da422c1b960..8c09436479564 100644 --- a/src/test/ui/issues/issue-38919.stderr +++ b/src/test/ui/issues/issue-38919.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `Item` found for type `T` in the current scope - --> $DIR/issue-38919.rs:2:5 + --> $DIR/issue-38919.rs:2:8 | LL | T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope - | ^^^^^^^ associated item not found in `T` + | ---^^^^ + | | + | associated item not found in `T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr index 7653cadc6a777..e851e79faee06 100644 --- a/src/test/ui/issues/issue-39559.stderr +++ b/src/test/ui/issues/issue-39559.stderr @@ -1,8 +1,10 @@ error[E0599]: no function or associated item named `dim` found for type `D` in the current scope - --> $DIR/issue-39559.rs:14:18 + --> $DIR/issue-39559.rs:14:21 | LL | entries: [T; D::dim()], - | ^^^^^^ function or associated item not found in `D` + | ---^^^ + | | + | function or associated item not found in `D` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `dim`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr index 0f9c15647492e..8e46d88018112 100644 --- a/src/test/ui/issues/issue-3973.stderr +++ b/src/test/ui/issues/issue-3973.stderr @@ -8,13 +8,15 @@ LL | | } | |_____^ not a member of trait `ToString_` error[E0599]: no function or associated item named `new` found for type `Point` in the current scope - --> $DIR/issue-3973.rs:22:13 + --> $DIR/issue-3973.rs:22:20 | LL | struct Point { | ------------ function or associated item `new` not found for this ... LL | let p = Point::new(0.0, 0.0); - | ^^^^^^^^^^ function or associated item not found in `Point` + | -------^^^ + | | + | function or associated item not found in `Point` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr index 7d8bae9cafc6f..36b9e8a1e8afa 100644 --- a/src/test/ui/issues/issue-42880.stderr +++ b/src/test/ui/issues/issue-42880.stderr @@ -1,8 +1,8 @@ error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope - --> $DIR/issue-42880.rs:4:15 + --> $DIR/issue-42880.rs:4:22 | LL | let f = |&Value::String(_)| (); //~ ERROR no associated item named - | ^^^^^^^^^^^^^^^^ associated item not found in `std::string::String` + | -------^^^^^^--- associated item not found in `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr index 169ce5429f5af..e30f04753762e 100644 --- a/src/test/ui/issues/issue-7950.stderr +++ b/src/test/ui/issues/issue-7950.stderr @@ -1,11 +1,13 @@ error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope - --> $DIR/issue-7950.rs:6:5 + --> $DIR/issue-7950.rs:6:10 | LL | struct Foo; | ----------- function or associated item `bar` not found for this ... LL | Foo::bar(); - | ^^^^^^^^ function or associated item not found in `Foo` + | -----^^^ + | | + | function or associated item not found in `Foo` error: aborting due to previous error diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 7ac629b5dea19..51313033a02dd 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -9,10 +9,12 @@ LL | use T; | error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope - --> $DIR/lexical-scopes.rs:10:5 + --> $DIR/lexical-scopes.rs:10:10 | LL | Foo::f(); //~ ERROR no function or associated item named `f` - | ^^^^^^ function or associated item not found in `Foo` + | -----^ + | | + | function or associated item not found in `Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr index dee32024e4702..9d35e167075ae 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `XXX` found for type `u32` in the current scope - --> $DIR/no-double-error.rs:8:9 + --> $DIR/no-double-error.rs:8:14 | LL | u32::XXX => { } //~ ERROR no associated item named - | ^^^^^^^^ associated item not found in `u32` + | -----^^^ + | | + | associated item not found in `u32` error: aborting due to previous error diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index e97cb3187846f..e4c17680c90a5 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -27,10 +27,12 @@ LL | x.baz(); //~ ERROR no method named `baz` | ^^^ error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope - --> $DIR/trait-import-suggestions.rs:30:13 + --> $DIR/trait-import-suggestions.rs:30:18 | LL | let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str` - | ^^^^^^^^^^^^^ function or associated item not found in `u32` + | -----^^^^^^^^ + | | + | function or associated item not found in `u32` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 5913f7b4b18a0..c65a9a3ed945c 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -33,26 +33,30 @@ LL | c.a(); //~ ERROR method `a` is private | ^ error[E0599]: no function or associated item named `a` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:78:5 + --> $DIR/trait-item-privacy.rs:78:8 | LL | struct S; | --------- function or associated item `a` not found for this ... LL | S::a(&S); - | ^^^^ function or associated item not found in `S` + | ---^ + | | + | function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `a`, perhaps you need to implement it: candidate #1: `method::A` error[E0599]: no function or associated item named `b` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:80:5 + --> $DIR/trait-item-privacy.rs:80:8 | LL | struct S; | --------- function or associated item `b` not found for this ... LL | S::b(&S); - | ^^^^ function or associated item not found in `S` + | ---^ + | | + | function or associated item not found in `S` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -67,26 +71,30 @@ LL | C::a(&S); //~ ERROR method `a` is private | ^^^^ error[E0599]: no associated item named `A` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:97:5 + --> $DIR/trait-item-privacy.rs:97:8 | LL | struct S; | --------- associated item `A` not found for this ... LL | S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope - | ^^^^ associated item not found in `S` + | ---^ + | | + | associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `A`, perhaps you need to implement it: candidate #1: `assoc_const::A` error[E0599]: no associated item named `B` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:98:5 + --> $DIR/trait-item-privacy.rs:98:8 | LL | struct S; | --------- associated item `B` not found for this ... LL | S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope - | ^^^^ associated item not found in `S` + | ---^ + | | + | associated item not found in `S` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 0297d883b8c59..a576fdde1173e 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -187,16 +187,20 @@ LL | let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN` error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope - --> $DIR/ufcs-partially-resolved.rs:38:5 + --> $DIR/ufcs-partially-resolved.rs:38:20 | LL | <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y` - | ^^^^^^^^^^^^^^^^^ associated item not found in `<u8 as Tr>::Y` + | ---------------^^ + | | + | associated item not found in `<u8 as Tr>::Y` error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope - --> $DIR/ufcs-partially-resolved.rs:55:5 + --> $DIR/ufcs-partially-resolved.rs:55:20 | LL | <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X` - | ^^^^^^^^^^^^^^^^ associated item not found in `<u8 as Dr>::X` + | ---------------^ + | | + | associated item not found in `<u8 as Dr>::X` error: aborting due to 32 previous errors diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr index cb7ee93338f68..b295b39d33c1d 100644 --- a/src/test/ui/unspecified-self-in-trait-ref.stderr +++ b/src/test/ui/unspecified-self-in-trait-ref.stderr @@ -1,26 +1,34 @@ error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:10:13 + --> $DIR/unspecified-self-in-trait-ref.rs:10:18 | LL | let a = Foo::lol(); - | ^^^^^^^^ function or associated item not found in `dyn Foo<_>` + | -----^^^ + | | + | function or associated item not found in `dyn Foo<_>` error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:12:13 + --> $DIR/unspecified-self-in-trait-ref.rs:12:23 | LL | let b = Foo::<_>::lol(); - | ^^^^^^^^^^^^^ function or associated item not found in `dyn Foo<_>` + | ----------^^^ + | | + | function or associated item not found in `dyn Foo<_>` error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:14:13 + --> $DIR/unspecified-self-in-trait-ref.rs:14:18 | LL | let c = Bar::lol(); - | ^^^^^^^^ function or associated item not found in `dyn Bar<_, _>` + | -----^^^ + | | + | function or associated item not found in `dyn Bar<_, _>` error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:16:13 + --> $DIR/unspecified-self-in-trait-ref.rs:16:30 | LL | let d = Bar::<usize, _>::lol(); - | ^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `dyn Bar<usize, _>` + | -----------------^^^ + | | + | function or associated item not found in `dyn Bar<usize, _>` error[E0393]: the type parameter `A` must be explicitly specified --> $DIR/unspecified-self-in-trait-ref.rs:18:13 From f30d29aab7005e59f76e4b4b560bcb8ddcfa6c8f Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Mon, 3 Dec 2018 01:08:41 +0000 Subject: [PATCH 013/124] Added chapter to Unstable Book. --- .../type-alias-enum-variants.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/type-alias-enum-variants.md diff --git a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md new file mode 100644 index 0000000000000..bcdeafc4b1137 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md @@ -0,0 +1,36 @@ +# `type_alias_enum_variants` + +The tracking issue for this feature is: [#49683] + +[#49683]: https://github.com/rust-lang/rust/issues/49683 + +------------------------ + +The `type_alias_enum_variants` feature enables the use of variants on type +aliases that refer to enums, as both a constructor and a pattern. That is, +it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same +as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type +`Enum`). + +Note that since `Self` exists as a type alias, this feature also enables the +use of the syntax `Self::Variant` within an impl block for an enum type. + +```rust +#![feature(type_alias_enum_variants)] + +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type Alias = Foo; + +fn main() { + let t = Alias::Bar(0); + let t = Alias::Baz { i: 0 }; + match t { + Alias::Bar(_i) => {} + Alias::Baz { i: _i } => {} + } +} +``` From 12b64b6837634c147d2173f1a58404fe2910850c Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Thu, 6 Dec 2018 04:22:56 +0000 Subject: [PATCH 014/124] Fixed issues raised in first review. --- src/librustc_typeck/astconv.rs | 17 ++++--- src/librustc_typeck/check/method/mod.rs | 12 ++--- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/lib.rs | 33 +++++-------- .../feature-gate-type_alias_enum_variants.rs | 4 -- ...ature-gate-type_alias_enum_variants.stderr | 46 ++----------------- 7 files changed, 33 insertions(+), 85 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 67f330536b85e..f15a27fbc8b59 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -31,7 +31,7 @@ use std::collections::BTreeSet; use std::iter; use std::slice; -use super::{allow_type_alias_enum_variants}; +use super::{check_type_alias_enum_variants_enabled}; pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -1277,7 +1277,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ref_id: ast::NodeId, span: Span, ty: Ty<'tcx>, - qself: &hir::Ty, ty_path_def: Def, item_segment: &hir::PathSegment) -> (Ty<'tcx>, Def) @@ -1296,10 +1295,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) }); if let Some(variant_def) = variant_def { - if allow_type_alias_enum_variants(tcx, qself, span) { - let def = Def::Variant(variant_def.did); - return (ty, def); - } + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::Variant(variant_def.did); + tcx.check_stability(def.def_id(), Some(ref_id), span); + return (ty, def); } } } @@ -1376,8 +1376,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident - }) - .expect("missing associated type"); + }).expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound); let ty = self.normalize_ty(span, ty); @@ -1618,7 +1617,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, qself, def, segment).0 + self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 4c96d476caa22..88814ae6a2db9 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -25,7 +25,7 @@ use rustc::infer::{self, InferOk}; use syntax::ast; use syntax_pos::Span; -use crate::{allow_type_alias_enum_variants}; +use crate::{check_type_alias_enum_variants_enabled}; use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { @@ -361,7 +361,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, method_name: ast::Ident, self_ty: Ty<'tcx>, - qself: &hir::Ty, expr_id: ast::NodeId) -> Result<Def, MethodError<'tcx>> { debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", @@ -379,10 +378,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.hygienic_eq(method_name, vd.ident, adt_def.did) }); if let Some(variant_def) = variant_def { - if allow_type_alias_enum_variants(tcx, qself, span) { - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - return Ok(def); - } + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); } } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index b368250b32d97..98c425655d2d3 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -645,7 +645,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, - rcvr_expr: Option<&hir::Expr>) -> bool { + source: SelfSource) -> bool { fn is_local(ty: Ty) -> bool { match ty.sty { ty::Adt(def, _) => def.did.is_local(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7e8c55a1f5601..5d0d07972c774 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4542,7 +4542,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Err }; let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, qself, def, segment); + ty, def, segment); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); @@ -4578,7 +4578,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return (*cached_def, Some(ty), slice::from_ref(&**item_segment)) } let item_name = item_segment.ident; - let def = match self.resolve_ufcs(span, item_name, ty, qself, node_id) { + let def = match self.resolve_ufcs(span, item_name, ty, node_id) { Ok(def) => def, Err(error) => { let def = match error { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 8c0913a56b514..c55a1258ce955 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -105,7 +105,6 @@ mod outlives; mod variance; use hir::Node; -use hir::def::Def; use rustc_target::spec::abi::Abi; use rustc::hir; use rustc::infer::InferOk; @@ -131,28 +130,20 @@ pub struct TypeAndSubsts<'tcx> { ty: Ty<'tcx>, } -fn allow_type_alias_enum_variants<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - qself: &hir::Ty, - span: Span) -> bool { - let allow_feature = tcx.features().type_alias_enum_variants; - if !allow_feature { - // Only print error if we know the type is an alias. - if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = qself.node { - if let Def::TyAlias(_) = path.def { - let mut err = tcx.sess.struct_span_err( - span, - "enum variants on type aliases are experimental" - ); - if nightly_options::is_nightly_build() { - help!(&mut err, - "add `#![feature(type_alias_enum_variants)]` to the \ - crate attributes to enable"); - } - err.emit(); - } +fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + span: Span) { + if !tcx.features().type_alias_enum_variants { + let mut err = tcx.sess.struct_span_err( + span, + "enum variants on type aliases are experimental" + ); + if nightly_options::is_nightly_build() { + help!(&mut err, + "add `#![feature(type_alias_enum_variants)]` to the \ + crate attributes to enable"); } + err.emit(); } - allow_feature } fn require_c_abi_if_variadic(tcx: TyCtxt, diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs index 2dcd0dcd24381..8997c1824ca6d 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs @@ -18,16 +18,12 @@ type Alias = Foo; fn main() { let t = Alias::Bar(0); //~^ ERROR enum variants on type aliases are experimental - //~^^ ERROR no variant named `Bar` found for type `Foo` in the current scope let t = Alias::Baz { i: 0 }; //~^ ERROR enum variants on type aliases are experimental - //~^^ ERROR ambiguous associated type match t { Alias::Bar(_i) => {} //~^ ERROR enum variants on type aliases are experimental - //~^^ ERROR no variant named `Bar` found for type `Foo` in the current scope Alias::Baz { i: _i } => {} //~^ ERROR enum variants on type aliases are experimental - //~^^ ERROR ambiguous associated type } } diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr index 7a49770d97a2f..cba643e18ca1a 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr @@ -6,67 +6,29 @@ LL | let t = Alias::Bar(0); | = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable -error[E0599]: no variant named `Bar` found for type `Foo` in the current scope - --> $DIR/feature-gate-type_alias_enum_variants.rs:19:20 - | -LL | enum Foo { - | -------- variant `Bar` not found here -... -LL | let t = Alias::Bar(0); - | -------^^^ - | | - | variant not found in `Foo` - | - = help: did you mean `Bar`? - error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:22:13 + --> $DIR/feature-gate-type_alias_enum_variants.rs:21:13 | LL | let t = Alias::Baz { i: 0 }; | ^^^^^^^^^^ | = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable -error[E0223]: ambiguous associated type - --> $DIR/feature-gate-type_alias_enum_variants.rs:22:13 - | -LL | let t = Alias::Baz { i: 0 }; - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` - error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:26:9 + --> $DIR/feature-gate-type_alias_enum_variants.rs:24:9 | LL | Alias::Bar(_i) => {} | ^^^^^^^^^^^^^^ | = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable -error[E0599]: no variant named `Bar` found for type `Foo` in the current scope - --> $DIR/feature-gate-type_alias_enum_variants.rs:26:16 - | -LL | enum Foo { - | -------- variant `Bar` not found here -... -LL | Alias::Bar(_i) => {} - | -------^^^---- variant not found in `Foo` - | - = help: did you mean `Bar`? - error: enum variants on type aliases are experimental - --> $DIR/feature-gate-type_alias_enum_variants.rs:29:9 + --> $DIR/feature-gate-type_alias_enum_variants.rs:26:9 | LL | Alias::Baz { i: _i } => {} | ^^^^^^^^^^ | = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable -error[E0223]: ambiguous associated type - --> $DIR/feature-gate-type_alias_enum_variants.rs:29:9 - | -LL | Alias::Baz { i: _i } => {} - | ^^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Baz` - -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0223, E0599. -For more information about an error, try `rustc --explain E0223`. From 06b716edcd52a987c21cc3ebc252b14f141467c1 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Fri, 7 Dec 2018 02:12:49 +0000 Subject: [PATCH 015/124] Work-around for shadowing of variant names with assoc const names in `libproc_macro/bridge/rpc.rs`. --- src/libproc_macro/bridge/rpc.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libproc_macro/bridge/rpc.rs b/src/libproc_macro/bridge/rpc.rs index 6685aa1acac39..74ae711a47372 100644 --- a/src/libproc_macro/bridge/rpc.rs +++ b/src/libproc_macro/bridge/rpc.rs @@ -71,15 +71,18 @@ macro_rules! rpc_encode_decode { (enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => { impl<S, $($($T: Encode<S>),+)*> Encode<S> for $name $(<$($T),+>)* { fn encode(self, w: &mut Writer, s: &mut S) { - // HACK(eddyb) `Tag` enum duplicated between the + // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. - #[repr(u8)] enum Tag { $($variant),* } #[allow(non_upper_case_globals)] - impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* } + mod tag { + #[repr(u8)] enum Tag { $($variant),* } + + $(pub const $variant: u8 = Tag::$variant as u8;)* + } match self { $($name::$variant $(($field))* => { - <Tag>::$variant.encode(w, s); + tag::$variant.encode(w, s); $($field.encode(w, s);)* })* } @@ -90,14 +93,17 @@ macro_rules! rpc_encode_decode { for $name $(<$($T),+>)* { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { - // HACK(eddyb) `Tag` enum duplicated between the + // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. - #[repr(u8)] enum Tag { $($variant),* } #[allow(non_upper_case_globals)] - impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* } + mod tag { + #[repr(u8)] enum Tag { $($variant),* } + + $(pub const $variant: u8 = Tag::$variant as u8;)* + } match u8::decode(r, s) { - $(<Tag>::$variant => { + $(tag::$variant => { $(let $field = DecodeMut::decode(r, s);)* $name::$variant $(($field))* })* From 2eeb93261000387ef754dfd9871e7ec8ed9716d3 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Thu, 13 Dec 2018 16:46:34 +0000 Subject: [PATCH 016/124] Added tests for enums & enum aliases with various combinations of generic args. --- src/test/run-pass/enum-generic-args.rs | 34 +++++++++++++ src/test/ui/enum-generic-args.rs | 35 +++++++++++++ src/test/ui/enum-generic-args.stderr | 70 ++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 src/test/run-pass/enum-generic-args.rs create mode 100644 src/test/ui/enum-generic-args.rs create mode 100644 src/test/ui/enum-generic-args.stderr diff --git a/src/test/run-pass/enum-generic-args.rs b/src/test/run-pass/enum-generic-args.rs new file mode 100644 index 0000000000000..f8cac550b41b6 --- /dev/null +++ b/src/test/run-pass/enum-generic-args.rs @@ -0,0 +1,34 @@ +#![feature(irrefutable_let_patterns)] +#![feature(type_alias_enum_variants)] + +#![allow(irrefutable_let_patterns)] + +enum Enum<T> { Variant(T) } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +macro_rules! is_variant { + ($expr:expr) => ( + assert!(if let Enum::Variant::<()>(_) = $expr { true } else { false }, + "expr does not have correct type"); + ) +} + +impl<T> Enum<T> { + fn foo() { + is_variant!(Self::Variant(())); + } +} + +fn main() { + is_variant!(Enum::Variant(())); + is_variant!(Enum::Variant::<()>(())); + is_variant!(Enum::<()>::Variant(())); + + is_variant!(Alias::Variant(())); + is_variant!(Alias::<()>::Variant(())); + + is_variant!(AliasFixed::Variant(())); + + Enum::<()>::foo(); +} diff --git a/src/test/ui/enum-generic-args.rs b/src/test/ui/enum-generic-args.rs new file mode 100644 index 0000000000000..21378b044e1b6 --- /dev/null +++ b/src/test/ui/enum-generic-args.rs @@ -0,0 +1,35 @@ +#![feature(type_alias_enum_variants)] + +enum Enum<T> { Variant(T) } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +impl<T> Enum<T> { + fn foo() { + Self::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::Variant(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR type parameters are not allowed on this type [E0109] + } +} + +fn main() { + Enum::<()>::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + Alias::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Alias::<()>::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + AliasFixed::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + AliasFixed::<()>::Variant(()); + //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + AliasFixed::<()>::Variant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] +} diff --git a/src/test/ui/enum-generic-args.stderr b/src/test/ui/enum-generic-args.stderr new file mode 100644 index 0000000000000..0807ee15dc757 --- /dev/null +++ b/src/test/ui/enum-generic-args.stderr @@ -0,0 +1,70 @@ +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:9:25 + | +LL | Self::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:11:16 + | +LL | Self::<()>::Variant(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:13:16 + | +LL | Self::<()>::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:13:31 + | +LL | Self::<()>::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:20:27 + | +LL | Enum::<()>::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:23:22 + | +LL | Alias::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:25:28 + | +LL | Alias::<()>::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:28:27 + | +LL | AliasFixed::Variant::<()>(()); + | ^^ type parameter not allowed + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-generic-args.rs:30:18 + | +LL | AliasFixed::<()>::Variant(()); + | ^^ unexpected type argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-generic-args.rs:32:18 + | +LL | AliasFixed::<()>::Variant::<()>(()); + | ^^ unexpected type argument + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-generic-args.rs:32:33 + | +LL | AliasFixed::<()>::Variant::<()>(()); + | ^^ type parameter not allowed + +error: aborting due to 11 previous errors + +Some errors occurred: E0107, E0109. +For more information about an error, try `rustc --explain E0107`. From f3704364d6b8bef4040b4e301cbf97945a463304 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Sat, 15 Dec 2018 04:40:09 +0000 Subject: [PATCH 017/124] Fixed issues raised in review. --- src/librustc_typeck/check/mod.rs | 49 ++++++++++++-------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5d0d07972c774..bf057a35b7bd2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5055,7 +5055,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Luckily, we can (at least for now) deduce the intermediate steps // just from the end-point. // - // There are basically four cases to consider: + // There are basically five cases to consider: // // 1. Reference to a constructor of a struct: // @@ -5117,37 +5117,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Case 2. Reference to a variant constructor. Def::VariantCtor(def_id, ..) => { - if self.tcx.features().type_alias_enum_variants { - let adt_def = self_ty.and_then(|t| t.ty_adt_def()); - let (generics_def_id, index) = if let Some(adt_def) = adt_def { - debug_assert!(adt_def.is_enum()); - (adt_def.did, last) - } else if last >= 1 && segments[last - 1].args.is_some() { - // Everything but the penultimate segment should have no - // parameters at all. - let enum_def_id = self.tcx.parent_def_id(def_id).unwrap(); - (enum_def_id, last - 1) - } else { - // FIXME: lint here suggesting `Enum::<...>::Variant` form - // instead of `Enum::Variant::<...>` form. - - // Everything but the final segment should have no - // parameters at all. - let generics = self.tcx.generics_of(def_id); - // Variant and struct constructors use the - // generics of their parent type definition. - (generics.parent.unwrap_or(def_id), last) - }; - path_segs.push(PathSeg(generics_def_id, index)); + let adt_def = self_ty.and_then(|t| t.ty_adt_def()); + let (generics_def_id, index) = if let Some(adt_def) = adt_def { + debug_assert!(adt_def.is_enum()); + (adt_def.did, last) + } else if last >= 1 && segments[last - 1].args.is_some() { + // Everything but the penultimate segment should have no + // parameters at all. + let enum_def_id = self.tcx.parent_def_id(def_id).unwrap(); + (enum_def_id, last - 1) } else { + // FIXME: lint here suggesting `Enum::<...>::Variant` form + // instead of `Enum::Variant::<...>` form. + // Everything but the final segment should have no // parameters at all. let generics = self.tcx.generics_of(def_id); // Variant and struct constructors use the // generics of their parent type definition. - let generics_def_id = generics.parent.unwrap_or(def_id); - path_segs.push(PathSeg(generics_def_id, last)); - } + (generics.parent.unwrap_or(def_id), last) + }; + path_segs.push(PathSeg(generics_def_id, index)); } // Case 3. Reference to a top-level value. @@ -5232,14 +5222,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let is_alias_variant_ctor = if tcx.features().type_alias_enum_variants { + let is_alias_variant_ctor = match def { Def::VariantCtor(_, _) if self_ty.is_some() => true, _ => false, - } - } else { - false - }; + }; let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { From f74f949b895990cbc5dbefffa234dd7b255be2a6 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Sat, 15 Dec 2018 14:48:52 +0000 Subject: [PATCH 018/124] Expanded tests for enum variants with generic args. --- src/test/run-pass/enum-generic-args.rs | 34 --- .../run-pass/enum-variant-generic-args.rs | 55 ++++ .../run-pass/type-alias-enum-variants-2.rs | 30 ++ src/test/ui/enum-generic-args.rs | 35 --- src/test/ui/enum-generic-args.stderr | 70 ----- src/test/ui/enum-variant-generic-args.rs | 65 +++++ src/test/ui/enum-variant-generic-args.stderr | 259 ++++++++++++++++++ src/test/ui/type-alias-enum-variants-panic.rs | 10 + 8 files changed, 419 insertions(+), 139 deletions(-) delete mode 100644 src/test/run-pass/enum-generic-args.rs create mode 100644 src/test/run-pass/enum-variant-generic-args.rs create mode 100644 src/test/run-pass/type-alias-enum-variants-2.rs delete mode 100644 src/test/ui/enum-generic-args.rs delete mode 100644 src/test/ui/enum-generic-args.stderr create mode 100644 src/test/ui/enum-variant-generic-args.rs create mode 100644 src/test/ui/enum-variant-generic-args.stderr create mode 100644 src/test/ui/type-alias-enum-variants-panic.rs diff --git a/src/test/run-pass/enum-generic-args.rs b/src/test/run-pass/enum-generic-args.rs deleted file mode 100644 index f8cac550b41b6..0000000000000 --- a/src/test/run-pass/enum-generic-args.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![feature(irrefutable_let_patterns)] -#![feature(type_alias_enum_variants)] - -#![allow(irrefutable_let_patterns)] - -enum Enum<T> { Variant(T) } -type Alias<T> = Enum<T>; -type AliasFixed = Enum<()>; - -macro_rules! is_variant { - ($expr:expr) => ( - assert!(if let Enum::Variant::<()>(_) = $expr { true } else { false }, - "expr does not have correct type"); - ) -} - -impl<T> Enum<T> { - fn foo() { - is_variant!(Self::Variant(())); - } -} - -fn main() { - is_variant!(Enum::Variant(())); - is_variant!(Enum::Variant::<()>(())); - is_variant!(Enum::<()>::Variant(())); - - is_variant!(Alias::Variant(())); - is_variant!(Alias::<()>::Variant(())); - - is_variant!(AliasFixed::Variant(())); - - Enum::<()>::foo(); -} diff --git a/src/test/run-pass/enum-variant-generic-args.rs b/src/test/run-pass/enum-variant-generic-args.rs new file mode 100644 index 0000000000000..bb4a4c9cf0c0c --- /dev/null +++ b/src/test/run-pass/enum-variant-generic-args.rs @@ -0,0 +1,55 @@ +#![feature(irrefutable_let_patterns)] +#![feature(type_alias_enum_variants)] + +#![allow(irrefutable_let_patterns)] + +enum Enum<T> { TSVariant(T), SVariant { v: T } } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +macro_rules! is_variant { + (TSVariant, $expr:expr) => (is_variant!(@TSVariant, (_), $expr)); + (SVariant, $expr:expr) => (is_variant!(@SVariant, { v: _ }, $expr)); + (@$variant:ident, $matcher:tt, $expr:expr) => ( + assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false }, + "expr does not have correct type"); + ); +} + +impl<T> Enum<T> { + fn ts_variant() { + is_variant!(TSVariant, Self::TSVariant(())); + } + + fn s_variant() { + is_variant!(SVariant, Self::SVariant { v: () }); + } +} + +fn main() { + // Tuple struct variant + + is_variant!(TSVariant, Enum::TSVariant(())); + is_variant!(TSVariant, Enum::TSVariant::<()>(())); + is_variant!(TSVariant, Enum::<()>::TSVariant(())); + + is_variant!(TSVariant, Alias::TSVariant(())); + is_variant!(TSVariant, Alias::<()>::TSVariant(())); + + is_variant!(TSVariant, AliasFixed::TSVariant(())); + + Enum::<()>::ts_variant(); + + // Struct variant + + is_variant!(SVariant, Enum::SVariant { v: () }); + is_variant!(SVariant, Enum::SVariant::<()> { v: () }); + is_variant!(SVariant, Enum::<()>::SVariant { v: () }); + + is_variant!(SVariant, Alias::SVariant { v: () }); + is_variant!(SVariant, Alias::<()>::SVariant { v: () }); + + is_variant!(SVariant, AliasFixed::SVariant { v: () }); + + Enum::<()>::s_variant(); +} diff --git a/src/test/run-pass/type-alias-enum-variants-2.rs b/src/test/run-pass/type-alias-enum-variants-2.rs new file mode 100644 index 0000000000000..0cf413babcbf6 --- /dev/null +++ b/src/test/run-pass/type-alias-enum-variants-2.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_enum_variants)] + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type FooAlias = Foo; +type OptionAlias = Option<i32>; + +impl Foo { + fn foo() -> Self { + Self::Bar(3) + } +} + +fn main() { + let t = FooAlias::Bar(1); + assert_eq!(t, Foo::Bar(1)); + let t = FooAlias::Baz { i: 2 }; + assert_eq!(t, Foo::Baz { i: 2 }); + match t { + FooAlias::Bar(_i) => {} + FooAlias::Baz { i } => { assert_eq!(i, 2); } + } + assert_eq!(Foo::foo(), Foo::Bar(3)); + + assert_eq!(OptionAlias::Some(4), Option::Some(4)); +} diff --git a/src/test/ui/enum-generic-args.rs b/src/test/ui/enum-generic-args.rs deleted file mode 100644 index 21378b044e1b6..0000000000000 --- a/src/test/ui/enum-generic-args.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![feature(type_alias_enum_variants)] - -enum Enum<T> { Variant(T) } -type Alias<T> = Enum<T>; -type AliasFixed = Enum<()>; - -impl<T> Enum<T> { - fn foo() { - Self::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - Self::<()>::Variant(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - Self::<()>::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - //~^^ ERROR type parameters are not allowed on this type [E0109] - } -} - -fn main() { - Enum::<()>::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - - Alias::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - Alias::<()>::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - - AliasFixed::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - AliasFixed::<()>::Variant(()); - //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] - AliasFixed::<()>::Variant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] -} diff --git a/src/test/ui/enum-generic-args.stderr b/src/test/ui/enum-generic-args.stderr deleted file mode 100644 index 0807ee15dc757..0000000000000 --- a/src/test/ui/enum-generic-args.stderr +++ /dev/null @@ -1,70 +0,0 @@ -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:9:25 - | -LL | Self::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:11:16 - | -LL | Self::<()>::Variant(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:13:16 - | -LL | Self::<()>::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:13:31 - | -LL | Self::<()>::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:20:27 - | -LL | Enum::<()>::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:23:22 - | -LL | Alias::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:25:28 - | -LL | Alias::<()>::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:28:27 - | -LL | AliasFixed::Variant::<()>(()); - | ^^ type parameter not allowed - -error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-generic-args.rs:30:18 - | -LL | AliasFixed::<()>::Variant(()); - | ^^ unexpected type argument - -error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-generic-args.rs:32:18 - | -LL | AliasFixed::<()>::Variant::<()>(()); - | ^^ unexpected type argument - -error[E0109]: type parameters are not allowed on this type - --> $DIR/enum-generic-args.rs:32:33 - | -LL | AliasFixed::<()>::Variant::<()>(()); - | ^^ type parameter not allowed - -error: aborting due to 11 previous errors - -Some errors occurred: E0107, E0109. -For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs new file mode 100644 index 0000000000000..37109e89624b0 --- /dev/null +++ b/src/test/ui/enum-variant-generic-args.rs @@ -0,0 +1,65 @@ +#![feature(type_alias_enum_variants)] + +enum Enum<T> { TSVariant(T), SVariant { v: T } } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +impl<T> Enum<T> { + fn ts_variant() { + Self::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::TSVariant(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR type parameters are not allowed on this type [E0109] + } + + fn s_variant() { + Self::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::SVariant(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Self::<()>::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR type parameters are not allowed on this type [E0109] + } +} + +fn main() { + // Tuple struct variant + + Enum::<()>::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + Alias::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Alias::<()>::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + AliasFixed::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + AliasFixed::<()>::TSVariant(()); + //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + AliasFixed::<()>::TSVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + + // Struct variant + + Enum::<()>::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + Alias::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + Alias::<()>::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + + AliasFixed::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + AliasFixed::<()>::SVariant(()); + //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + AliasFixed::<()>::SVariant::<()>(()); + //~^ ERROR type parameters are not allowed on this type [E0109] + //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] +} diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr new file mode 100644 index 0000000000000..4cae164b6ff46 --- /dev/null +++ b/src/test/ui/enum-variant-generic-args.stderr @@ -0,0 +1,259 @@ +error[E0423]: expected function, found struct variant `Enum::SVariant` + --> $DIR/enum-variant-generic-args.rs:50:5 + | +LL | Enum::<()>::SVariant::<()>(()); + | ^^^^^^^^^^^^--------^^^^^^ + | | | + | | did you mean `TSVariant`? + | did you mean `Enum::SVariant { /* fields */ }`? + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:9:27 + | +LL | Self::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:11:16 + | +LL | Self::<()>::TSVariant(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:13:16 + | +LL | Self::<()>::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:13:33 + | +LL | Self::<()>::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:19:26 + | +LL | Self::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<Self>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:19:9 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<Self>::SVariant::<()>` defined here +... +LL | Self::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<Self>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <Self>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:21:16 + | +LL | Self::<()>::SVariant(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<Self<()>>::SVariant` + --> $DIR/enum-variant-generic-args.rs:21:9 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<Self<()>>::SVariant` defined here +... +LL | Self::<()>::SVariant(()); + | ^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<Self<()>>::SVariant` is a unit variant, you need to write it without the parenthesis + | +LL | <Self<()>>::SVariant; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:23:16 + | +LL | Self::<()>::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:23:32 + | +LL | Self::<()>::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<Self<()>>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:23:9 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<Self<()>>::SVariant::<()>` defined here +... +LL | Self::<()>::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<Self<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <Self<()>>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:32:29 + | +LL | Enum::<()>::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:35:24 + | +LL | Alias::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:37:30 + | +LL | Alias::<()>::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:40:29 + | +LL | AliasFixed::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:42:18 + | +LL | AliasFixed::<()>::TSVariant(()); + | ^^ unexpected type argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:44:18 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | ^^ unexpected type argument + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:44:35 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:53:23 + | +LL | Alias::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<Alias>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:53:5 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<Alias>::SVariant::<()>` defined here +... +LL | Alias::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<Alias>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <Alias>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:55:29 + | +LL | Alias::<()>::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<Alias<()>>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:55:5 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<Alias<()>>::SVariant::<()>` defined here +... +LL | Alias::<()>::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<Alias<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <Alias<()>>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:58:28 + | +LL | AliasFixed::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<AliasFixed>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:58:5 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<AliasFixed>::SVariant::<()>` defined here +... +LL | AliasFixed::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<AliasFixed>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <AliasFixed>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:60:18 + | +LL | AliasFixed::<()>::SVariant(()); + | ^^ unexpected type argument + +error[E0618]: expected function, found enum variant `<AliasFixed<()>>::SVariant` + --> $DIR/enum-variant-generic-args.rs:60:5 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<AliasFixed<()>>::SVariant` defined here +... +LL | AliasFixed::<()>::SVariant(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<AliasFixed<()>>::SVariant` is a unit variant, you need to write it without the parenthesis + | +LL | <AliasFixed<()>>::SVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:62:18 + | +LL | AliasFixed::<()>::SVariant::<()>(()); + | ^^ unexpected type argument + +error[E0109]: type parameters are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:62:34 + | +LL | AliasFixed::<()>::SVariant::<()>(()); + | ^^ type parameter not allowed + +error[E0618]: expected function, found enum variant `<AliasFixed<()>>::SVariant::<()>` + --> $DIR/enum-variant-generic-args.rs:62:5 + | +LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } + | ----------------- `<AliasFixed<()>>::SVariant::<()>` defined here +... +LL | AliasFixed::<()>::SVariant::<()>(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | + | call expression requires function +help: `<AliasFixed<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis + | +LL | <AliasFixed<()>>::SVariant::<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 30 previous errors + +Some errors occurred: E0107, E0109, E0423, E0618. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/type-alias-enum-variants-panic.rs b/src/test/ui/type-alias-enum-variants-panic.rs new file mode 100644 index 0000000000000..abed190d22b0c --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-panic.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_enum_variants)] + +enum Enum { Variant {} } +type Alias = Enum; + +fn main() { + Alias::Variant; + let Alias::Variant = panic!(); + let Alias::Variant(..) = panic!(); +} From 8b6769cfecc01e11b337f4717d5c0eb48a697693 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Sat, 15 Dec 2018 14:54:33 +0000 Subject: [PATCH 019/124] Removed unnecessary special handling of `VariantCtor` defs in `instantiate_value_path`. --- src/librustc_typeck/check/mod.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bf057a35b7bd2..7db8ee67aa11b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5314,22 +5314,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - Def::VariantCtor(_, _) if self_ty.is_some() => { - let def_id = def.def_id(); - - let ty = tcx.type_of(def_id); - if tcx.features().type_alias_enum_variants { - if let Some(self_ty) = self_ty { - match ty.ty_adt_def() { - Some(adt_def) if adt_def.is_enum() => { - return (self_ty, def); - } - _ => {} - } - } - } - (def_id, ty) - } _ => { let def_id = def.def_id(); From 72d498db09e3d98f2289335f10347810c119bae8 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Mon, 17 Dec 2018 18:49:45 +0000 Subject: [PATCH 020/124] Fixed several ICEs. --- src/librustc_typeck/check/_match.rs | 14 +- src/librustc_typeck/check/mod.rs | 145 ++++++++++-------- src/test/ui/type-alias-enum-variants-panic.rs | 7 + .../ui/type-alias-enum-variants-panic.stderr | 22 +++ 4 files changed, 116 insertions(+), 72 deletions(-) create mode 100644 src/test/ui/type-alias-enum-variants-panic.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4e3cb5c7f1c0d..923be2a76aa66 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -17,6 +17,8 @@ use util::nodemap::FxHashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::cmp; +use super::report_unexpected_variant_def; + impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// The `is_arg` argument indicates whether this pattern is the /// *outermost* pattern in an argument (e.g., in `fn foo(&x: @@ -736,12 +738,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); expected: Ty<'tcx>) -> Ty<'tcx> { let tcx = self.tcx; - let report_unexpected_def = |def: Def| { - span_err!(tcx.sess, pat.span, E0533, - "expected unit struct/variant or constant, found {} `{}`", - def.kind_name(), - hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); - }; // Resolve the path and check the definition for errors. let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span); @@ -751,7 +747,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); return tcx.types.err; } Def::Method(..) => { - report_unexpected_def(def); + report_unexpected_variant_def(tcx, &def, pat.span, qpath); + return tcx.types.err; + } + Def::VariantCtor(_, CtorKind::Fictive) => { + report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } Def::VariantCtor(_, CtorKind::Const) | diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7db8ee67aa11b..6902e9faadf63 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -85,8 +85,8 @@ mod op; use astconv::AstConv; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; -use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind}; -use rustc::hir::def::Def; +use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath}; +use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -1864,6 +1864,16 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_representable(tcx, sp, def_id); } +fn report_unexpected_variant_def<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + def: &Def, + span: Span, + qpath: &QPath) { + span_err!(tcx.sess, span, E0533, + "expected unit struct/variant or constant, found {} `{}`", + def.kind_name(), + hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); +} + impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } @@ -2947,7 +2957,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let is_closure = match arg.node { - hir::ExprKind::Closure(..) => true, + ExprKind::Closure(..) => true, _ => false }; @@ -3097,8 +3107,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - // Add help to type error if this is an `if` condition with an assignment - if let (ExpectIfCondition, &hir::ExprKind::Assign(ref lhs, ref rhs)) + // Add help to type error if this is an `if` condition with an assignment. + if let (ExpectIfCondition, &ExprKind::Assign(ref lhs, ref rhs)) = (expected, &expr.node) { let msg = "try comparing for equality"; @@ -3691,12 +3701,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_struct_path(&self, - qpath: &hir::QPath, + qpath: &QPath, node_id: ast::NodeId) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { let path_span = match *qpath { - hir::QPath::Resolved(_, ref path) => path.span, - hir::QPath::TypeRelative(ref qself, _) => qself.span + QPath::Resolved(_, ref path) => path.span, + QPath::TypeRelative(ref qself, _) => qself.span }; let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, node_id); let variant = match def { @@ -3749,7 +3759,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_struct(&self, expr: &hir::Expr, expected: Expectation<'tcx>, - qpath: &hir::QPath, + qpath: &QPath, fields: &'gcx [hir::Field], base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx> { @@ -3763,8 +3773,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let path_span = match *qpath { - hir::QPath::Resolved(_, ref path) => path.span, - hir::QPath::TypeRelative(ref qself, _) => qself.span + QPath::Resolved(_, ref path) => path.span, + QPath::TypeRelative(ref qself, _) => qself.span }; // Prohibit struct expressions when non-exhaustive flag is set. @@ -3836,9 +3846,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Warn for non-block expressions with diverging children. match expr.node { - hir::ExprKind::Block(..) | - hir::ExprKind::Loop(..) | hir::ExprKind::While(..) | - hir::ExprKind::If(..) | hir::ExprKind::Match(..) => {} + ExprKind::Block(..) | + ExprKind::Loop(..) | ExprKind::While(..) | + ExprKind::If(..) | ExprKind::Match(..) => {} _ => self.warn_if_unreachable(expr.id, expr.span, "expression") } @@ -3879,7 +3889,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let id = expr.id; match expr.node { - hir::ExprKind::Box(ref subexpr) => { + ExprKind::Box(ref subexpr) => { let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| { match ty.sty { ty::Adt(def, _) if def.is_box() @@ -3891,16 +3901,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_box(referent_ty) } - hir::ExprKind::Lit(ref lit) => { + ExprKind::Lit(ref lit) => { self.check_lit(&lit, expected) } - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + ExprKind::Binary(op, ref lhs, ref rhs) => { self.check_binop(expr, op, lhs, rhs) } - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + ExprKind::AssignOp(op, ref lhs, ref rhs) => { self.check_binop_assign(expr, op, lhs, rhs) } - hir::ExprKind::Unary(unop, ref oprnd) => { + ExprKind::Unary(unop, ref oprnd) => { let expected_inner = match unop { hir::UnNot | hir::UnNeg => { expected @@ -3968,7 +3978,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } oprnd_t } - hir::ExprKind::AddrOf(mutbl, ref oprnd) => { + ExprKind::AddrOf(mutbl, ref oprnd) => { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { match ty.sty { ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { @@ -4008,13 +4018,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_ref(region, tm) } } - hir::ExprKind::Path(ref qpath) => { + ExprKind::Path(ref qpath) => { let (def, opt_ty, segs) = self.resolve_ty_and_def_ufcs(qpath, expr.id, expr.span); - let ty = if def != Def::Err { - self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0 - } else { - self.set_tainted_by_errors(); - tcx.types.err + let ty = match def { + Def::Err => { + self.set_tainted_by_errors(); + tcx.types.err + } + Def::VariantCtor(_, CtorKind::Fictive) => { + report_unexpected_variant_def(tcx, &def, expr.span, qpath); + tcx.types.err + } + _ => self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0, }; if let ty::FnDef(..) = ty.sty { @@ -4061,13 +4076,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - hir::ExprKind::InlineAsm(_, ref outputs, ref inputs) => { + ExprKind::InlineAsm(_, ref outputs, ref inputs) => { for expr in outputs.iter().chain(inputs.iter()) { self.check_expr(expr); } tcx.mk_unit() } - hir::ExprKind::Break(destination, ref expr_opt) => { + ExprKind::Break(destination, ref expr_opt) => { if let Ok(target_id) = destination.target_id { let (e_ty, cause); if let Some(ref e) = *expr_opt { @@ -4140,7 +4155,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // ... except when we try to 'break rust;'. // ICE this expression in particular (see #43162). - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = e.node { + if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.node { if path.segments.len() == 1 && path.segments[0].ident.name == "rust" { fatally_break_rust(self.tcx.sess); } @@ -4151,7 +4166,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - hir::ExprKind::Continue(destination) => { + ExprKind::Continue(destination) => { if destination.target_id.is_ok() { tcx.types.never } else { @@ -4159,7 +4174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err } } - hir::ExprKind::Ret(ref expr_opt) => { + ExprKind::Ret(ref expr_opt) => { if self.ret_coercion.is_none() { struct_span_err!(self.tcx.sess, expr.span, E0572, "return statement outside of function body").emit(); @@ -4191,7 +4206,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.types.never } - hir::ExprKind::Assign(ref lhs, ref rhs) => { + ExprKind::Assign(ref lhs, ref rhs) => { let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); @@ -4221,11 +4236,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_unit() } } - hir::ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { + ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { self.check_then_else(&cond, then_expr, opt_else_expr.as_ref().map(|e| &**e), expr.span, expected) } - hir::ExprKind::While(ref cond, ref body, _) => { + ExprKind::While(ref cond, ref body, _) => { let ctxt = BreakableCtxt { // cannot use break with a value from a while loop coerce: None, @@ -4249,7 +4264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_unit() } - hir::ExprKind::Loop(ref body, _, source) => { + ExprKind::Loop(ref body, _, source) => { let coerce = match source { // you can only use break with a value from a normal `loop { }` hir::LoopSource::Loop => { @@ -4289,22 +4304,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.mk_unit()) } - hir::ExprKind::Match(ref discrim, ref arms, match_src) => { + ExprKind::Match(ref discrim, ref arms, match_src) => { self.check_match(expr, &discrim, arms, expected, match_src) } - hir::ExprKind::Closure(capture, ref decl, body_id, _, gen) => { + ExprKind::Closure(capture, ref decl, body_id, _, gen) => { self.check_expr_closure(expr, capture, &decl, body_id, gen, expected) } - hir::ExprKind::Block(ref body, _) => { + ExprKind::Block(ref body, _) => { self.check_block_with_expected(&body, expected) } - hir::ExprKind::Call(ref callee, ref args) => { + ExprKind::Call(ref callee, ref args) => { self.check_call(expr, &callee, args, expected) } - hir::ExprKind::MethodCall(ref segment, span, ref args) => { + ExprKind::MethodCall(ref segment, span, ref args) => { self.check_method_call(expr, segment, span, args, expected, needs) } - hir::ExprKind::Cast(ref e, ref t) => { + ExprKind::Cast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. let t_cast = self.to_ty_saving_user_provided_ty(t); @@ -4329,12 +4344,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - hir::ExprKind::Type(ref e, ref t) => { + ExprKind::Type(ref e, ref t) => { let ty = self.to_ty_saving_user_provided_ty(&t); self.check_expr_eq_type(&e, ty); ty } - hir::ExprKind::Array(ref args) => { + ExprKind::Array(ref args) => { let uty = expected.to_option(self).and_then(|uty| { match uty.sty { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), @@ -4358,7 +4373,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; tcx.mk_array(element_ty, args.len() as u64) } - hir::ExprKind::Repeat(ref element, ref count) => { + ExprKind::Repeat(ref element, ref count) => { let count_def_id = tcx.hir().local_def_id(count.id); let param_env = ty::ParamEnv::empty(); let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); @@ -4414,7 +4429,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err } } - hir::ExprKind::Tup(ref elts) => { + ExprKind::Tup(ref elts) => { let flds = expected.only_has_type(self).and_then(|ty| { let ty = self.resolve_type_vars_with_obligations(ty); match ty.sty { @@ -4444,13 +4459,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tuple } } - hir::ExprKind::Struct(ref qpath, ref fields, ref base_expr) => { + ExprKind::Struct(ref qpath, ref fields, ref base_expr) => { self.check_expr_struct(expr, expected, qpath, fields, base_expr) } - hir::ExprKind::Field(ref base, field) => { + ExprKind::Field(ref base, field) => { self.check_field(expr, needs, &base, field) } - hir::ExprKind::Index(ref base, ref idx) => { + ExprKind::Index(ref base, ref idx) => { let base_t = self.check_expr_with_needs(&base, needs); let idx_t = self.check_expr(&idx); @@ -4476,7 +4491,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: - if let hir::ExprKind::Lit(ref lit) = idx.node { + if let ExprKind::Lit(ref lit) = idx.node { if let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node { let snip = tcx.sess.source_map().span_to_snippet(base.span); @@ -4501,7 +4516,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - hir::ExprKind::Yield(ref value) => { + ExprKind::Yield(ref value) => { match self.yield_ty { Some(ty) => { self.check_expr_coercable_to_type(&value, ty); @@ -4522,21 +4537,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path(&self, - qpath: &hir::QPath, + qpath: &QPath, path_span: Span, node_id: ast::NodeId) -> (Def, Ty<'tcx>) { match *qpath { - hir::QPath::Resolved(ref maybe_qself, ref path) => { + QPath::Resolved(ref maybe_qself, ref path) => { let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); let ty = AstConv::def_to_ty(self, self_ty, path, true); (path.def, ty) } - hir::QPath::TypeRelative(ref qself, ref segment) => { + QPath::TypeRelative(ref qself, ref segment) => { let ty = self.to_ty(qself); - let def = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.node { + let def = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.node { path.def } else { Def::Err @@ -4556,18 +4571,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Resolve associated value path into a base type and associated constant or method definition. // The newly resolved definition is written into `type_dependent_defs`. pub fn resolve_ty_and_def_ufcs<'b>(&self, - qpath: &'b hir::QPath, + qpath: &'b QPath, node_id: ast::NodeId, span: Span) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) { let (ty, qself, item_segment) = match *qpath { - hir::QPath::Resolved(ref opt_qself, ref path) => { + QPath::Resolved(ref opt_qself, ref path) => { return (path.def, opt_qself.as_ref().map(|qself| self.to_ty(qself)), &path.segments[..]); } - hir::QPath::TypeRelative(ref qself, ref segment) => { + QPath::TypeRelative(ref qself, ref segment) => { (self.to_ty(qself), qself, segment) } }; @@ -4933,13 +4948,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `BlockTailExpression` only relevant if the tail expr would be // useful on its own. match expression.node { - hir::ExprKind::Call(..) | - hir::ExprKind::MethodCall(..) | - hir::ExprKind::If(..) | - hir::ExprKind::While(..) | - hir::ExprKind::Loop(..) | - hir::ExprKind::Match(..) | - hir::ExprKind::Block(..) => { + ExprKind::Call(..) | + ExprKind::MethodCall(..) | + ExprKind::If(..) | + ExprKind::While(..) | + ExprKind::Loop(..) | + ExprKind::Match(..) | + ExprKind::Block(..) => { let sp = self.tcx.sess.source_map().next_point(cause_span); err.span_suggestion_with_applicability( sp, @@ -5447,7 +5462,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If our calling expression is indeed the function itself, we're good! // If not, generate an error that this can only be called directly. if let Node::Expr(expr) = self.tcx.hir().get(self.tcx.hir().get_parent_node(node_id)) { - if let hir::ExprKind::Call(ref callee, ..) = expr.node { + if let ExprKind::Call(ref callee, ..) = expr.node { if callee.id == node_id { return } diff --git a/src/test/ui/type-alias-enum-variants-panic.rs b/src/test/ui/type-alias-enum-variants-panic.rs index abed190d22b0c..f97592f5d3b15 100644 --- a/src/test/ui/type-alias-enum-variants-panic.rs +++ b/src/test/ui/type-alias-enum-variants-panic.rs @@ -1,10 +1,17 @@ +// ignore-tidy-linelength + #![feature(type_alias_enum_variants)] +#![allow(unreachable_code)] + enum Enum { Variant {} } type Alias = Enum; fn main() { Alias::Variant; + //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533] let Alias::Variant = panic!(); + //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533] let Alias::Variant(..) = panic!(); + //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164] } diff --git a/src/test/ui/type-alias-enum-variants-panic.stderr b/src/test/ui/type-alias-enum-variants-panic.stderr new file mode 100644 index 0000000000000..3480d116383ee --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-panic.stderr @@ -0,0 +1,22 @@ +error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:11:5 + | +LL | Alias::Variant; + | ^^^^^^^^^^^^^^ + +error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:13:9 + | +LL | let Alias::Variant = panic!(); + | ^^^^^^^^^^^^^^ + +error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:15:9 + | +LL | let Alias::Variant(..) = panic!(); + | ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 3 previous errors + +Some errors occurred: E0164, E0533. +For more information about an error, try `rustc --explain E0164`. From 89a33ddebf4a2f850068574302b865bd7ef8a2b3 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Tue, 18 Dec 2018 00:40:22 +0000 Subject: [PATCH 021/124] Added regression test for using generic parameters on modules. --- src/librustc/hir/mod.rs | 2 +- src/librustc_typeck/astconv.rs | 6 +- src/librustc_typeck/diagnostics.rs | 2 +- src/test/ui/enum-variant-generic-args.rs | 36 ++--- src/test/ui/enum-variant-generic-args.stderr | 68 ++++----- src/test/ui/error-codes/E0109.stderr | 4 +- src/test/ui/error-codes/E0110.stderr | 12 +- src/test/ui/issues/issue-22706.rs | 2 +- src/test/ui/issues/issue-22706.stderr | 4 +- src/test/ui/mod-subitem-as-enum-variant.rs | 10 ++ .../ui/mod-subitem-as-enum-variant.stderr | 9 ++ src/test/ui/prim-with-args.rs | 44 +++--- src/test/ui/prim-with-args.stderr | 132 +++++++++--------- .../ui/qualified/qualified-path-params-2.rs | 2 +- .../qualified/qualified-path-params-2.stderr | 4 +- .../collections.rs | 12 +- .../collections.stderr | 20 +-- .../construct_with_other_type.rs | 8 +- .../construct_with_other_type.stderr | 12 +- ...ic_associated_type_undeclared_lifetimes.rs | 8 +- ...ssociated_type_undeclared_lifetimes.stderr | 12 +- .../iterable.rs | 14 +- .../iterable.stderr | 24 ++-- .../parameter_number_and_kind.rs | 12 +- .../parameter_number_and_kind.stderr | 20 +-- .../pointer_family.rs | 10 +- .../pointer_family.stderr | 16 +-- .../streaming_iterator.rs | 12 +- .../streaming_iterator.stderr | 20 +-- .../ui/structs/struct-path-associated-type.rs | 6 +- .../struct-path-associated-type.stderr | 14 +- src/test/ui/structs/struct-path-self.rs | 6 +- src/test/ui/structs/struct-path-self.stderr | 16 +-- src/test/ui/type-alias-enum-variants.rs | 2 +- src/test/ui/type-alias-enum-variants.stderr | 4 +- 35 files changed, 306 insertions(+), 279 deletions(-) create mode 100644 src/test/ui/mod-subitem-as-enum-variant.rs create mode 100644 src/test/ui/mod-subitem-as-enum-variant.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 969e1c3620eb7..e6fa079207e59 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -420,7 +420,7 @@ pub struct GenericArgs { /// The generic arguments for this path segment. pub args: HirVec<GenericArg>, /// Bindings (equality constraints) on associated types, if present. - /// E.g., `Foo<A=Bar>`. + /// E.g., `Foo<A = Bar>`. pub bindings: HirVec<TypeBinding>, /// Were arguments written in parenthesized form `Fn(T) -> U`? /// This is required mostly for pretty-printing and diagnostics, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f15a27fbc8b59..2679f03377206 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1437,7 +1437,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if err_for_lt { continue } err_for_lt = true; (struct_span_err!(self.tcx().sess, lt.span, E0110, - "lifetime parameters are not allowed on this type"), + "lifetime arguments are not allowed on this entity"), lt.span, "lifetime") } @@ -1445,12 +1445,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if err_for_ty { continue } err_for_ty = true; (struct_span_err!(self.tcx().sess, ty.span, E0109, - "type parameters are not allowed on this type"), + "type arguments are not allowed on this entity"), ty.span, "type") } }; - span_err.span_label(span, format!("{} parameter not allowed", kind)) + span_err.span_label(span, format!("{} argument not allowed", kind)) .emit(); if err_for_lt && err_for_ty { break; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 425b428ecf2db..5910a8b3110d0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1291,7 +1291,7 @@ You tried to give a type parameter to a type which doesn't need it. Erroneous code example: ```compile_fail,E0109 -type X = u32<i32>; // error: type parameters are not allowed on this type +type X = u32<i32>; // error: type arguments are not allowed on this entity ``` Please check that you used the correct type and recheck its definition. Perhaps diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs index 37109e89624b0..2ae4b756b7c05 100644 --- a/src/test/ui/enum-variant-generic-args.rs +++ b/src/test/ui/enum-variant-generic-args.rs @@ -7,22 +7,22 @@ type AliasFixed = Enum<()>; impl<T> Enum<T> { fn ts_variant() { Self::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::TSVariant(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - //~^^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR type arguments are not allowed on this entity [E0109] } fn s_variant() { Self::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::SVariant(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] - //~^^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR type arguments are not allowed on this entity [E0109] } } @@ -30,36 +30,36 @@ fn main() { // Tuple struct variant Enum::<()>::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Alias::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Alias::<()>::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] AliasFixed::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] AliasFixed::<()>::TSVariant(()); //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] AliasFixed::<()>::TSVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] // Struct variant Enum::<()>::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Alias::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Alias::<()>::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] AliasFixed::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] AliasFixed::<()>::SVariant(()); //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] AliasFixed::<()>::SVariant::<()>(()); - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] } diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr index 4cae164b6ff46..2d622a49e20af 100644 --- a/src/test/ui/enum-variant-generic-args.stderr +++ b/src/test/ui/enum-variant-generic-args.stderr @@ -7,35 +7,35 @@ LL | Enum::<()>::SVariant::<()>(()); | | did you mean `TSVariant`? | did you mean `Enum::SVariant { /* fields */ }`? -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:9:27 | LL | Self::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:11:16 | LL | Self::<()>::TSVariant(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:13:16 | LL | Self::<()>::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:13:33 | LL | Self::<()>::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:19:26 | LL | Self::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<Self>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:19:9 @@ -52,11 +52,11 @@ help: `<Self>::SVariant::<()>` is a unit variant, you need to write it without t LL | <Self>::SVariant::<()>; | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:21:16 | LL | Self::<()>::SVariant(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<Self<()>>::SVariant` --> $DIR/enum-variant-generic-args.rs:21:9 @@ -73,17 +73,17 @@ help: `<Self<()>>::SVariant` is a unit variant, you need to write it without the LL | <Self<()>>::SVariant; | ^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:23:16 | LL | Self::<()>::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:23:32 | LL | Self::<()>::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<Self<()>>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:23:9 @@ -100,29 +100,29 @@ help: `<Self<()>>::SVariant::<()>` is a unit variant, you need to write it witho LL | <Self<()>>::SVariant::<()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:32:29 | LL | Enum::<()>::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:35:24 | LL | Alias::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:37:30 | LL | Alias::<()>::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:40:29 | LL | AliasFixed::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0107]: wrong number of type arguments: expected 0, found 1 --> $DIR/enum-variant-generic-args.rs:42:18 @@ -136,17 +136,17 @@ error[E0107]: wrong number of type arguments: expected 0, found 1 LL | AliasFixed::<()>::TSVariant::<()>(()); | ^^ unexpected type argument -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:44:35 | LL | AliasFixed::<()>::TSVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:53:23 | LL | Alias::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<Alias>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:53:5 @@ -163,11 +163,11 @@ help: `<Alias>::SVariant::<()>` is a unit variant, you need to write it without LL | <Alias>::SVariant::<()>; | ^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:55:29 | LL | Alias::<()>::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<Alias<()>>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:55:5 @@ -184,11 +184,11 @@ help: `<Alias<()>>::SVariant::<()>` is a unit variant, you need to write it with LL | <Alias<()>>::SVariant::<()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:58:28 | LL | AliasFixed::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<AliasFixed>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:58:5 @@ -232,11 +232,11 @@ error[E0107]: wrong number of type arguments: expected 0, found 1 LL | AliasFixed::<()>::SVariant::<()>(()); | ^^ unexpected type argument -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:62:34 | LL | AliasFixed::<()>::SVariant::<()>(()); - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0618]: expected function, found enum variant `<AliasFixed<()>>::SVariant::<()>` --> $DIR/enum-variant-generic-args.rs:62:5 diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr index 447b106c6296b..a5508f9808576 100644 --- a/src/test/ui/error-codes/E0109.stderr +++ b/src/test/ui/error-codes/E0109.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/E0109.rs:1:14 | LL | type X = u32<i32>; //~ ERROR E0109 - | ^^^ type parameter not allowed + | ^^^ type argument not allowed error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index 609b8b58276ff..be9b4229aeb60 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -1,8 +1,16 @@ -error[E0110]: lifetime parameters are not allowed on this type +<<<<<<< HEAD +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/E0110.rs:1:14 +||||||| merged common ancestors +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/E0110.rs:11:14 +======= +error[E0110]: lifetime arguments are not allowed on this entity + --> $DIR/E0110.rs:11:14 +>>>>>>> Added regression test for using generic parameters on modules. | LL | type X = u32<'static>; //~ ERROR E0110 - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22706.rs b/src/test/ui/issues/issue-22706.rs index c19c2a4c7059b..413a0d9a4943a 100644 --- a/src/test/ui/issues/issue-22706.rs +++ b/src/test/ui/issues/issue-22706.rs @@ -1,3 +1,3 @@ fn is_copy<T: ::std::marker<i32>::Copy>() {} -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] fn main() {} diff --git a/src/test/ui/issues/issue-22706.stderr b/src/test/ui/issues/issue-22706.stderr index 57e62599b196f..a3cf716903d20 100644 --- a/src/test/ui/issues/issue-22706.stderr +++ b/src/test/ui/issues/issue-22706.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/issue-22706.rs:1:29 | LL | fn is_copy<T: ::std::marker<i32>::Copy>() {} - | ^^^ type parameter not allowed + | ^^^ type argument not allowed error: aborting due to previous error diff --git a/src/test/ui/mod-subitem-as-enum-variant.rs b/src/test/ui/mod-subitem-as-enum-variant.rs new file mode 100644 index 0000000000000..ec809d44e942a --- /dev/null +++ b/src/test/ui/mod-subitem-as-enum-variant.rs @@ -0,0 +1,10 @@ + +mod Mod { + pub struct FakeVariant<T>(pub T); +} + +fn main() { + Mod::FakeVariant::<i32>(0); + Mod::<i32>::FakeVariant(0); + //~^ ERROR type arguments are not allowed on this entity [E0109] +} diff --git a/src/test/ui/mod-subitem-as-enum-variant.stderr b/src/test/ui/mod-subitem-as-enum-variant.stderr new file mode 100644 index 0000000000000..d62bad81c3d8d --- /dev/null +++ b/src/test/ui/mod-subitem-as-enum-variant.stderr @@ -0,0 +1,9 @@ +error[E0109]: type arguments are not allowed on this entity + --> $DIR/mod-subitem-as-enum-variant.rs:8:11 + | +LL | Mod::<i32>::FakeVariant(0); + | ^^^ type argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/prim-with-args.rs b/src/test/ui/prim-with-args.rs index 52443a729e5bc..b5df0fb76ca6a 100644 --- a/src/test/ui/prim-with-args.rs +++ b/src/test/ui/prim-with-args.rs @@ -1,27 +1,27 @@ fn main() { -let x: isize<isize>; //~ ERROR type parameters are not allowed on this type -let x: i8<isize>; //~ ERROR type parameters are not allowed on this type -let x: i16<isize>; //~ ERROR type parameters are not allowed on this type -let x: i32<isize>; //~ ERROR type parameters are not allowed on this type -let x: i64<isize>; //~ ERROR type parameters are not allowed on this type -let x: usize<isize>; //~ ERROR type parameters are not allowed on this type -let x: u8<isize>; //~ ERROR type parameters are not allowed on this type -let x: u16<isize>; //~ ERROR type parameters are not allowed on this type -let x: u32<isize>; //~ ERROR type parameters are not allowed on this type -let x: u64<isize>; //~ ERROR type parameters are not allowed on this type -let x: char<isize>; //~ ERROR type parameters are not allowed on this type +let x: isize<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i8<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i16<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i32<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i64<isize>; //~ ERROR type arguments are not allowed on this entity +let x: usize<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u8<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u16<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u32<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u64<isize>; //~ ERROR type arguments are not allowed on this entity +let x: char<isize>; //~ ERROR type arguments are not allowed on this entity -let x: isize<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i8<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i16<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i32<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i64<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: usize<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u8<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u16<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u32<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u64<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: char<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: char<'static>; //~ ERROR lifetime arguments are not allowed on this entity } diff --git a/src/test/ui/prim-with-args.stderr b/src/test/ui/prim-with-args.stderr index 190c45a1624d1..91259e87efc02 100644 --- a/src/test/ui/prim-with-args.stderr +++ b/src/test/ui/prim-with-args.stderr @@ -1,134 +1,134 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:3:14 | -LL | let x: isize<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: isize<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:4:11 | -LL | let x: i8<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i8<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:5:12 | -LL | let x: i16<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i16<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:6:12 | -LL | let x: i32<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i32<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:7:12 | -LL | let x: i64<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i64<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:8:14 | -LL | let x: usize<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: usize<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:9:11 | -LL | let x: u8<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u8<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:10:12 | -LL | let x: u16<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u16<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:11:12 | -LL | let x: u32<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u32<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:12:12 | -LL | let x: u64<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u64<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:13:13 | -LL | let x: char<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: char<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:15:14 | -LL | let x: isize<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:16:11 | -LL | let x: i8<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:17:12 | -LL | let x: i16<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:18:12 | -LL | let x: i32<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:19:12 | -LL | let x: i64<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:20:14 | -LL | let x: usize<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:21:11 | -LL | let x: u8<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:22:12 | -LL | let x: u16<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:23:12 | -LL | let x: u32<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:24:12 | -LL | let x: u64<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:25:13 | -LL | let x: char<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: char<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed error: aborting due to 22 previous errors diff --git a/src/test/ui/qualified/qualified-path-params-2.rs b/src/test/ui/qualified/qualified-path-params-2.rs index 6ee55f54bdbb5..8412983fda549 100644 --- a/src/test/ui/qualified/qualified-path-params-2.rs +++ b/src/test/ui/qualified/qualified-path-params-2.rs @@ -16,7 +16,7 @@ impl S { } type A = <S as Tr>::A::f<u8>; -//~^ ERROR type parameters are not allowed on this type +//~^ ERROR type arguments are not allowed on this entity //~| ERROR ambiguous associated type fn main() {} diff --git a/src/test/ui/qualified/qualified-path-params-2.stderr b/src/test/ui/qualified/qualified-path-params-2.stderr index 91c3d704cb9dd..4e073841b9740 100644 --- a/src/test/ui/qualified/qualified-path-params-2.stderr +++ b/src/test/ui/qualified/qualified-path-params-2.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/qualified-path-params-2.rs:18:26 | LL | type A = <S as Tr>::A::f<u8>; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/qualified-path-params-2.rs:18:10 diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.rs b/src/test/ui/rfc1598-generic-associated-types/collections.rs index e1a65c28803e2..5414bb4a6d20e 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.rs +++ b/src/test/ui/rfc1598-generic-associated-types/collections.rs @@ -2,7 +2,7 @@ //~^ WARNING the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. // A Collection trait and collection families. Based on @@ -15,14 +15,14 @@ trait Collection<T> { // Test associated type defaults with parameters type Sibling<U>: Collection<U> = <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] fn empty() -> Self; fn add(&mut self, value: T); fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } trait CollectionFamily { @@ -48,13 +48,13 @@ impl<T> Collection<T> for Vec<T> { } fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32> -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] where C: Collection<i32>, { @@ -66,7 +66,7 @@ where } fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] where C: Collection<i32>, { diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr index e90a6b8ad138c..b3fb81b418e8c 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/collections.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:56:90 | LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32> - | ^^^ type parameter not allowed + | ^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:68:69 | LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> - | ^^^ type parameter not allowed + | ^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:17:71 | LL | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:24:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; - | ^^^^^ lifetime parameter not allowed + | ^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:50:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { - | ^^^^^ lifetime parameter not allowed + | ^^^^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs index 85935d1cca6bf..d9c482e23e47c 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs @@ -3,7 +3,7 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Foo { @@ -15,15 +15,15 @@ trait Baz { // This weird type tests that we can use universal function call syntax to access the Item on type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } impl<T> Baz for T where T: Foo { type Quux<'a> = T; type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr index 100809f62a55c..fd6116d2da23a 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr @@ -4,23 +4,23 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:17:46 | LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:17:63 | LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:25:40 | LL | type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs index bfdd12003885a..2e6d7470b49a2 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -3,20 +3,20 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Iterable { type Item<'a>; type Iter<'a>: Iterator<Item = Self::Item<'a>> - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] + Deref<Target = Self::Item<'b>>; //~^ ERROR undeclared lifetime - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; //~^ ERROR undeclared lifetime - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index f5b42866dc6b4..3cebab6389557 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -16,23 +16,23 @@ error[E0261]: use of undeclared lifetime name `'undeclared` LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; | ^^^^^^^^^^^ undeclared lifetime -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:47 | LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37 | LL | + Deref<Target = Self::Item<'b>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; - | ^^^^^^^^^^^ lifetime parameter not allowed + | ^^^^^^^^^^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs index 16ed4a7546cc3..69258506651c4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.rs +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.rs @@ -3,16 +3,16 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Iterable { type Item<'a>; type Iter<'a>: Iterator<Item = Self::Item<'a>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] fn iter<'a>(&'a self) -> Self::Iter<'a>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } // Impl for struct type @@ -21,7 +21,7 @@ impl<T> Iterable for Vec<T> { type Iter<'a> = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } @@ -32,18 +32,18 @@ impl<T> Iterable for [T] { type Iter<'a> = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] it.iter() } fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] it.iter().next() } diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr index 41943d7d325e9..cc3ade6f39d90 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr @@ -4,41 +4,41 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:11:47 | LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:40:53 | LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:45:60 | LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:14:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:23:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:34:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 6 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs index 098d52b20faae..851e331a0e965 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs @@ -2,7 +2,7 @@ //~^ WARNING the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. // FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`. @@ -15,13 +15,13 @@ trait Foo { type E<'a, T>; // Test parameters in default values type FOk<T> = Self::E<'static, T>; - //~^ ERROR type parameters are not allowed on this type [E0109] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] type FErr1 = Self::E<'static, 'static>; // Error - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] type FErr2<T> = Self::E<'static, T, u32>; // Error - //~^ ERROR type parameters are not allowed on this type [E0109] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } struct Fooy; diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr index dfd1648e5c0d6..265b0fab77061 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:17:27 | LL | type FOk<T> = Self::E<'static, T>; - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:17:36 | LL | type FOk<T> = Self::E<'static, T>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:20:26 | LL | type FErr1 = Self::E<'static, 'static>; // Error - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:22:29 | LL | type FErr2<T> = Self::E<'static, T, u32>; // Error - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:22:38 | LL | type FErr2<T> = Self::E<'static, T, u32>; // Error - | ^ type parameter not allowed + | ^ type argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs index e11670ce1b316..2d188aed42778 100644 --- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs @@ -1,7 +1,7 @@ #![feature(generic_associated_types)] //~^ WARNING the feature `generic_associated_types` is incomplete -// FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR. +// FIXME(#44265): "type argument not allowed" errors will be addressed in a follow-up PR. use std::rc::Rc; use std::sync::Arc; @@ -10,7 +10,7 @@ use std::ops::Deref; trait PointerFamily { type Pointer<T>: Deref<Target = T>; fn new<T>(value: T) -> Self::Pointer<T>; - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] } struct ArcFamily; @@ -18,7 +18,7 @@ struct ArcFamily; impl PointerFamily for ArcFamily { type Pointer<T> = Arc<T>; fn new<T>(value: T) -> Self::Pointer<T> { - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Arc::new(value) } } @@ -28,14 +28,14 @@ struct RcFamily; impl PointerFamily for RcFamily { type Pointer<T> = Rc<T>; fn new<T>(value: T) -> Self::Pointer<T> { - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Rc::new(value) } } struct Foo<P: PointerFamily> { bar: P::Pointer<String>, - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr index 29c442a79e628..2b9eed2a688a2 100644 --- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr @@ -4,29 +4,29 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:37:21 | LL | bar: P::Pointer<String>, - | ^^^^^^ type parameter not allowed + | ^^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:12:42 | LL | fn new<T>(value: T) -> Self::Pointer<T>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:20:42 | LL | fn new<T>(value: T) -> Self::Pointer<T> { - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:30:42 | LL | fn new<T>(value: T) -> Self::Pointer<T> { - | ^ type parameter not allowed + | ^ type argument not allowed error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs index cb6e576804937..1ef154447903b 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs @@ -1,7 +1,7 @@ #![feature(generic_associated_types)] //~^ WARNING the feature `generic_associated_types` is incomplete -// FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime argument not allowed on this type" errors will be addressed in a // follow-up PR use std::fmt::Display; @@ -10,13 +10,13 @@ trait StreamingIterator { type Item<'a>; // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. fn next<'a>(&'a self) -> Option<Self::Item<'a>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } struct Foo<T: StreamingIterator> { // Applying a concrete lifetime to the constructor outside the trait. bar: <T as StreamingIterator>::Item<'static>, - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } // Users can bound parameters by the type constructed by that trait's associated type constructor @@ -24,7 +24,7 @@ struct Foo<T: StreamingIterator> { //FIXME(sunjay): This next line should parse and be valid //fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ } fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } -//~^ ERROR lifetime parameters are not allowed on this type [E0110] +//~^ ERROR lifetime arguments are not allowed on this entity [E0110] // Full example of enumerate iterator @@ -36,9 +36,9 @@ struct StreamEnumerate<I> { impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> { type Item<'a> = (usize, I::Item<'a>); - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] fn next<'a>(&'a self) -> Option<Self::Item<'a>> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] match self.iter.next() { None => None, Some(val) => { diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr index af5d1b872cc6e..5afbba5d2d744 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:18:41 | LL | bar: <T as StreamingIterator>::Item<'static>, - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:26:64 | LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:12:48 | LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:38:37 | LL | type Item<'a> = (usize, I::Item<'a>); - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:40:48 | LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs index 1cafe265b2e0e..7c770852d22d2 100644 --- a/src/test/ui/structs/struct-path-associated-type.rs +++ b/src/test/ui/structs/struct-path-associated-type.rs @@ -13,7 +13,7 @@ fn f<T: Tr>() { //~^ ERROR expected struct, variant or union type, found associated type let z = T::A::<u8> {}; //~^ ERROR expected struct, variant or union type, found associated type - //~| ERROR type parameters are not allowed on this type + //~| ERROR type arguments are not allowed on this entity match S { T::A {} => {} //~^ ERROR expected struct, variant or union type, found associated type @@ -22,7 +22,7 @@ fn f<T: Tr>() { fn g<T: Tr<A = S>>() { let s = T::A {}; // OK - let z = T::A::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this entity match S { T::A {} => {} // OK } @@ -31,7 +31,7 @@ fn g<T: Tr<A = S>>() { fn main() { let s = S::A {}; //~ ERROR ambiguous associated type let z = S::A::<u8> {}; //~ ERROR ambiguous associated type - //~^ ERROR type parameters are not allowed on this type + //~^ ERROR type arguments are not allowed on this entity match S { S::A {} => {} //~ ERROR ambiguous associated type } diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr index 41360d87930d1..80824d9847838 100644 --- a/src/test/ui/structs/struct-path-associated-type.stderr +++ b/src/test/ui/structs/struct-path-associated-type.stderr @@ -4,11 +4,11 @@ error[E0071]: expected struct, variant or union type, found associated type LL | let s = T::A {}; | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:14:20 | LL | let z = T::A::<u8> {}; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0071]: expected struct, variant or union type, found associated type --> $DIR/struct-path-associated-type.rs:14:13 @@ -22,11 +22,11 @@ error[E0071]: expected struct, variant or union type, found associated type LL | T::A {} => {} | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:25:20 | -LL | let z = T::A::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 @@ -34,11 +34,11 @@ error[E0223]: ambiguous associated type LL | let s = S::A {}; //~ ERROR ambiguous associated type | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:33:20 | LL | let z = S::A::<u8> {}; //~ ERROR ambiguous associated type - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs index ccbf3db29b1d9..51ed9e5457eb7 100644 --- a/src/test/ui/structs/struct-path-self.rs +++ b/src/test/ui/structs/struct-path-self.rs @@ -6,7 +6,7 @@ trait Tr { //~^ ERROR expected struct, variant or union type, found Self let z = Self::<u8> {}; //~^ ERROR expected struct, variant or union type, found Self - //~| ERROR type parameters are not allowed on this type + //~| ERROR type arguments are not allowed on this entity match s { Self { .. } => {} //~^ ERROR expected struct, variant or union type, found Self @@ -17,7 +17,7 @@ trait Tr { impl Tr for S { fn f() { let s = Self {}; // OK - let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity match s { Self { .. } => {} // OK } @@ -27,7 +27,7 @@ impl Tr for S { impl S { fn g() { let s = Self {}; // OK - let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity match s { Self { .. } => {} // OK } diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr index a1df1a0764ccb..cda6b7a533f65 100644 --- a/src/test/ui/structs/struct-path-self.stderr +++ b/src/test/ui/structs/struct-path-self.stderr @@ -4,11 +4,11 @@ error[E0071]: expected struct, variant or union type, found Self LL | let s = Self {}; | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:7:24 | LL | let z = Self::<u8> {}; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0071]: expected struct, variant or union type, found Self --> $DIR/struct-path-self.rs:7:17 @@ -22,17 +22,17 @@ error[E0071]: expected struct, variant or union type, found Self LL | Self { .. } => {} | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:20:24 | -LL | let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:30:24 | -LL | let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs index 73395e6a9798a..3ec200d57c55d 100644 --- a/src/test/ui/type-alias-enum-variants.rs +++ b/src/test/ui/type-alias-enum-variants.rs @@ -7,5 +7,5 @@ fn main() { let _ = Option::None::<u8>; // OK (Lint in future!) let _ = Alias::<u8>::None; // OK let _ = Alias::None::<u8>; // Error - //~^ type parameters are not allowed on this type + //~^ type arguments are not allowed on this entity } diff --git a/src/test/ui/type-alias-enum-variants.stderr b/src/test/ui/type-alias-enum-variants.stderr index e7003217c8d7c..cf81f5b27ac6b 100644 --- a/src/test/ui/type-alias-enum-variants.stderr +++ b/src/test/ui/type-alias-enum-variants.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/type-alias-enum-variants.rs:9:27 | LL | let _ = Alias::None::<u8>; // Error - | ^^ type parameter not allowed + | ^^ type argument not allowed error: aborting due to previous error From f79535b0d0cbeba03377a16ac1835f64e841ec84 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Tue, 18 Dec 2018 18:59:00 +0000 Subject: [PATCH 022/124] Fixed handling of unit variants of aliased enums in type NS. --- src/librustc_typeck/astconv.rs | 152 +++++++++++++- src/librustc_typeck/check/mod.rs | 132 +----------- .../run-pass/enum-variant-generic-args.rs | 6 +- src/test/ui/enum-variant-generic-args.rs | 21 +- src/test/ui/enum-variant-generic-args.stderr | 198 +++++------------- 5 files changed, 215 insertions(+), 294 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2679f03377206..98013dd00dc70 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -32,6 +32,10 @@ use std::iter; use std::slice; use super::{check_type_alias_enum_variants_enabled}; +use rustc_data_structures::fx::FxHashSet; + +#[derive(Debug)] +pub struct PathSeg(pub DefId, pub usize); pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -1470,6 +1474,134 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { err.span_label(span, "associated type not allowed here").emit(); } + pub fn def_ids_for_path_segments(&self, + segments: &[hir::PathSegment], + self_ty: Option<Ty<'tcx>>, + def: Def) + -> Vec<PathSeg> { + // We need to extract the type parameters supplied by the user in + // the path `path`. Due to the current setup, this is a bit of a + // tricky-process; the problem is that resolve only tells us the + // end-point of the path resolution, and not the intermediate steps. + // Luckily, we can (at least for now) deduce the intermediate steps + // just from the end-point. + // + // There are basically five cases to consider: + // + // 1. Reference to a constructor of a struct: + // + // struct Foo<T>(...) + // + // In this case, the parameters are declared in the type space. + // + // 2. Reference to a constructor of an enum variant: + // + // enum E<T> { Foo(...) } + // + // In this case, the parameters are defined in the type space, + // but may be specified either on the type or the variant. + // + // 3. Reference to a fn item or a free constant: + // + // fn foo<T>() { } + // + // In this case, the path will again always have the form + // `a::b::foo::<T>` where only the final segment should have + // type parameters. However, in this case, those parameters are + // declared on a value, and hence are in the `FnSpace`. + // + // 4. Reference to a method or an associated constant: + // + // impl<A> SomeStruct<A> { + // fn foo<B>(...) + // } + // + // Here we can have a path like + // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters + // may appear in two places. The penultimate segment, + // `SomeStruct::<A>`, contains parameters in TypeSpace, and the + // final segment, `foo::<B>` contains parameters in fn space. + // + // 5. Reference to a local variable + // + // Local variables can't have any type parameters. + // + // The first step then is to categorize the segments appropriately. + + let tcx = self.tcx(); + + assert!(!segments.is_empty()); + let last = segments.len() - 1; + + let mut path_segs = vec![]; + + match def { + // Case 1. Reference to a struct constructor. + Def::StructCtor(def_id, ..) | + Def::SelfCtor(.., def_id) => { + // Everything but the final segment should have no + // parameters at all. + let generics = tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + let generics_def_id = generics.parent.unwrap_or(def_id); + path_segs.push(PathSeg(generics_def_id, last)); + } + + // Case 2. Reference to a variant constructor. + Def::Variant(def_id) | + Def::VariantCtor(def_id, ..) => { + let adt_def = self_ty.and_then(|t| t.ty_adt_def()); + let (generics_def_id, index) = if let Some(adt_def) = adt_def { + debug_assert!(adt_def.is_enum()); + (adt_def.did, last) + } else if last >= 1 && segments[last - 1].args.is_some() { + // Everything but the penultimate segment should have no + // parameters at all. + let enum_def_id = tcx.parent_def_id(def_id).unwrap(); + (enum_def_id, last - 1) + } else { + // FIXME: lint here recommending `Enum::<...>::Variant` form + // instead of `Enum::Variant::<...>` form. + + // Everything but the final segment should have no + // parameters at all. + let generics = tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + (generics.parent.unwrap_or(def_id), last) + }; + path_segs.push(PathSeg(generics_def_id, index)); + } + + // Case 3. Reference to a top-level value. + Def::Fn(def_id) | + Def::Const(def_id) | + Def::Static(def_id, _) => { + path_segs.push(PathSeg(def_id, last)); + } + + // Case 4. Reference to a method or associated const. + Def::Method(def_id) | + Def::AssociatedConst(def_id) => { + if segments.len() >= 2 { + let generics = tcx.generics_of(def_id); + path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); + } + path_segs.push(PathSeg(def_id, last)); + } + + // Case 5. Local variable, no generics. + Def::Local(..) | Def::Upvar(..) => {} + + _ => bug!("unexpected definition: {:?}", def), + } + + debug!("path_segs = {:?}", path_segs); + + path_segs + } + // Check a type `Path` and convert it to a `Ty`. pub fn def_to_ty(&self, opt_self_ty: Option<Ty<'tcx>>, @@ -1500,14 +1632,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, did, path.segments.last().unwrap()) } - Def::Variant(did) if permit_variants => { + Def::Variant(_) if permit_variants => { // Convert "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. assert_eq!(opt_self_ty, None); - self.prohibit_generics(path.segments.split_last().unwrap().1); - self.ast_path_to_ty(span, - tcx.parent_def_id(did).unwrap(), - path.segments.last().unwrap()) + + let path_segs = self.def_ids_for_path_segments(&path.segments, None, path.def); + let generic_segs: FxHashSet<_> = + path_segs.iter().map(|PathSeg(_, index)| index).collect(); + self.prohibit_generics(path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !generic_segs.contains(&index) { + Some(seg) + } else { + None + } + })); + + let PathSeg(def_id, index) = path_segs.last().unwrap(); + self.ast_path_to_ty(span, *def_id, &path.segments[*index]) } Def::TyParam(did) => { assert_eq!(opt_self_ty, None); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6902e9faadf63..3f9faab58919e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -83,7 +83,7 @@ mod generator_interior; mod intrinsic; mod op; -use astconv::AstConv; +use astconv::{AstConv, PathSeg}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath}; use rustc::hir::def::{CtorKind, Def}; @@ -507,9 +507,6 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> { } } -#[derive(Debug)] -struct PathSeg(DefId, usize); - pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { body_id: ast::NodeId, @@ -5058,131 +5055,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MachineApplicable); } - fn def_ids_for_path_segments(&self, - segments: &[hir::PathSegment], - self_ty: Option<Ty<'tcx>>, - def: Def) - -> Vec<PathSeg> { - // We need to extract the type parameters supplied by the user in - // the path `path`. Due to the current setup, this is a bit of a - // tricky-process; the problem is that resolve only tells us the - // end-point of the path resolution, and not the intermediate steps. - // Luckily, we can (at least for now) deduce the intermediate steps - // just from the end-point. - // - // There are basically five cases to consider: - // - // 1. Reference to a constructor of a struct: - // - // struct Foo<T>(...) - // - // In this case, the parameters are declared in the type space. - // - // 2. Reference to a constructor of an enum variant: - // - // enum E<T> { Foo(...) } - // - // In this case, the parameters are defined in the type space, - // but may be specified either on the type or the variant. - // - // 3. Reference to a fn item or a free constant: - // - // fn foo<T>() { } - // - // In this case, the path will again always have the form - // `a::b::foo::<T>` where only the final segment should have - // type parameters. However, in this case, those parameters are - // declared on a value, and hence are in the `FnSpace`. - // - // 4. Reference to a method or an associated constant: - // - // impl<A> SomeStruct<A> { - // fn foo<B>(...) - // } - // - // Here we can have a path like - // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters - // may appear in two places. The penultimate segment, - // `SomeStruct::<A>`, contains parameters in TypeSpace, and the - // final segment, `foo::<B>` contains parameters in fn space. - // - // 5. Reference to a local variable - // - // Local variables can't have any type parameters. - // - // The first step then is to categorize the segments appropriately. - - assert!(!segments.is_empty()); - let last = segments.len() - 1; - - let mut path_segs = vec![]; - - match def { - // Case 1. Reference to a struct constructor. - Def::StructCtor(def_id, ..) | - Def::SelfCtor(.., def_id) => { - // Everything but the final segment should have no - // parameters at all. - let generics = self.tcx.generics_of(def_id); - // Variant and struct constructors use the - // generics of their parent type definition. - let generics_def_id = generics.parent.unwrap_or(def_id); - path_segs.push(PathSeg(generics_def_id, last)); - } - - // Case 2. Reference to a variant constructor. - Def::VariantCtor(def_id, ..) => { - let adt_def = self_ty.and_then(|t| t.ty_adt_def()); - let (generics_def_id, index) = if let Some(adt_def) = adt_def { - debug_assert!(adt_def.is_enum()); - (adt_def.did, last) - } else if last >= 1 && segments[last - 1].args.is_some() { - // Everything but the penultimate segment should have no - // parameters at all. - let enum_def_id = self.tcx.parent_def_id(def_id).unwrap(); - (enum_def_id, last - 1) - } else { - // FIXME: lint here suggesting `Enum::<...>::Variant` form - // instead of `Enum::Variant::<...>` form. - - // Everything but the final segment should have no - // parameters at all. - let generics = self.tcx.generics_of(def_id); - // Variant and struct constructors use the - // generics of their parent type definition. - (generics.parent.unwrap_or(def_id), last) - }; - path_segs.push(PathSeg(generics_def_id, index)); - } - - // Case 3. Reference to a top-level value. - Def::Fn(def_id) | - Def::Const(def_id) | - Def::Static(def_id, _) => { - path_segs.push(PathSeg(def_id, last)); - } - - // Case 4. Reference to a method or associated const. - Def::Method(def_id) | - Def::AssociatedConst(def_id) => { - if segments.len() >= 2 { - let generics = self.tcx.generics_of(def_id); - path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); - } - path_segs.push(PathSeg(def_id, last)); - } - - // Case 5. Local variable, no generics. - Def::Local(..) | Def::Upvar(..) => {} - - _ => bug!("unexpected definition: {:?}", def), - } - - debug!("path_segs = {:?}", path_segs); - - path_segs - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, @@ -5202,7 +5074,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - let path_segs = self.def_ids_for_path_segments(segments, self_ty, def); + let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def); let mut user_self_ty = None; match def { diff --git a/src/test/run-pass/enum-variant-generic-args.rs b/src/test/run-pass/enum-variant-generic-args.rs index bb4a4c9cf0c0c..ace4ebdfa0595 100644 --- a/src/test/run-pass/enum-variant-generic-args.rs +++ b/src/test/run-pass/enum-variant-generic-args.rs @@ -8,9 +8,9 @@ type Alias<T> = Enum<T>; type AliasFixed = Enum<()>; macro_rules! is_variant { - (TSVariant, $expr:expr) => (is_variant!(@TSVariant, (_), $expr)); - (SVariant, $expr:expr) => (is_variant!(@SVariant, { v: _ }, $expr)); - (@$variant:ident, $matcher:tt, $expr:expr) => ( + (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr)); + (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr)); + (@check $variant:ident, $matcher:tt, $expr:expr) => ( assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false }, "expr does not have correct type"); ); diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs index 2ae4b756b7c05..044d8438815ba 100644 --- a/src/test/ui/enum-variant-generic-args.rs +++ b/src/test/ui/enum-variant-generic-args.rs @@ -16,13 +16,16 @@ impl<T> Enum<T> { } fn s_variant() { - Self::SVariant::<()>(()); + Self::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - Self::<()>::SVariant(()); + //~^^ ERROR mismatched types [E0308] + Self::<()>::SVariant { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - Self::<()>::SVariant::<()>(()); + //~^^ ERROR mismatched types [E0308] + Self::<()>::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR type arguments are not allowed on this entity [E0109] + //~^^^ ERROR mismatched types [E0308] } } @@ -47,19 +50,19 @@ fn main() { // Struct variant - Enum::<()>::SVariant::<()>(()); + Enum::<()>::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - Alias::SVariant::<()>(()); + Alias::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - Alias::<()>::SVariant::<()>(()); + Alias::<()>::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - AliasFixed::SVariant::<()>(()); + AliasFixed::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] - AliasFixed::<()>::SVariant(()); + AliasFixed::<()>::SVariant { v: () }; //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] - AliasFixed::<()>::SVariant::<()>(()); + AliasFixed::<()>::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] } diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr index 2d622a49e20af..4228a807bad16 100644 --- a/src/test/ui/enum-variant-generic-args.stderr +++ b/src/test/ui/enum-variant-generic-args.stderr @@ -1,12 +1,3 @@ -error[E0423]: expected function, found struct variant `Enum::SVariant` - --> $DIR/enum-variant-generic-args.rs:50:5 - | -LL | Enum::<()>::SVariant::<()>(()); - | ^^^^^^^^^^^^--------^^^^^^ - | | | - | | did you mean `TSVariant`? - | did you mean `Enum::SVariant { /* fields */ }`? - error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:9:27 | @@ -34,226 +25,139 @@ LL | Self::<()>::TSVariant::<()>(()); error[E0109]: type arguments are not allowed on this entity --> $DIR/enum-variant-generic-args.rs:19:26 | -LL | Self::SVariant::<()>(()); +LL | Self::SVariant::<()> { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<Self>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:19:9 +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:19:35 | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<Self>::SVariant::<()>` defined here -... -LL | Self::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<Self>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis +LL | Self::SVariant::<()> { v: () }; + | ^^ expected type parameter, found () | -LL | <Self>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `T` + found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:21:16 + --> $DIR/enum-variant-generic-args.rs:22:16 | -LL | Self::<()>::SVariant(()); +LL | Self::<()>::SVariant { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<Self<()>>::SVariant` - --> $DIR/enum-variant-generic-args.rs:21:9 +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:22:35 | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<Self<()>>::SVariant` defined here -... -LL | Self::<()>::SVariant(()); - | ^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<Self<()>>::SVariant` is a unit variant, you need to write it without the parenthesis +LL | Self::<()>::SVariant { v: () }; + | ^^ expected type parameter, found () | -LL | <Self<()>>::SVariant; - | ^^^^^^^^^^^^^^^^^^^^ + = note: expected type `T` + found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:23:16 + --> $DIR/enum-variant-generic-args.rs:25:16 | -LL | Self::<()>::SVariant::<()>(()); +LL | Self::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:23:32 + --> $DIR/enum-variant-generic-args.rs:25:32 | -LL | Self::<()>::SVariant::<()>(()); +LL | Self::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<Self<()>>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:23:9 +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:25:41 | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<Self<()>>::SVariant::<()>` defined here -... -LL | Self::<()>::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<Self<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis +LL | Self::<()>::SVariant::<()> { v: () }; + | ^^ expected type parameter, found () | -LL | <Self<()>>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `T` + found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:32:29 + --> $DIR/enum-variant-generic-args.rs:35:29 | LL | Enum::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:35:24 + --> $DIR/enum-variant-generic-args.rs:38:24 | LL | Alias::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:37:30 + --> $DIR/enum-variant-generic-args.rs:40:30 | LL | Alias::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:40:29 + --> $DIR/enum-variant-generic-args.rs:43:29 | LL | AliasFixed::TSVariant::<()>(()); | ^^ type argument not allowed error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:42:18 + --> $DIR/enum-variant-generic-args.rs:45:18 | LL | AliasFixed::<()>::TSVariant(()); | ^^ unexpected type argument error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:44:18 + --> $DIR/enum-variant-generic-args.rs:47:18 | LL | AliasFixed::<()>::TSVariant::<()>(()); | ^^ unexpected type argument error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:44:35 + --> $DIR/enum-variant-generic-args.rs:47:35 | LL | AliasFixed::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:53:23 + --> $DIR/enum-variant-generic-args.rs:53:28 | -LL | Alias::SVariant::<()>(()); - | ^^ type argument not allowed +LL | Enum::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<Alias>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:53:5 - | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<Alias>::SVariant::<()>` defined here -... -LL | Alias::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<Alias>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:56:23 | -LL | <Alias>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | Alias::SVariant::<()> { v: () }; + | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:55:29 + --> $DIR/enum-variant-generic-args.rs:58:29 | -LL | Alias::<()>::SVariant::<()>(()); +LL | Alias::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<Alias<()>>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:55:5 - | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<Alias<()>>::SVariant::<()>` defined here -... -LL | Alias::<()>::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<Alias<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis - | -LL | <Alias<()>>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:58:28 + --> $DIR/enum-variant-generic-args.rs:61:28 | -LL | AliasFixed::SVariant::<()>(()); +LL | AliasFixed::SVariant::<()> { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<AliasFixed>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:58:5 - | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<AliasFixed>::SVariant::<()>` defined here -... -LL | AliasFixed::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<AliasFixed>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis - | -LL | <AliasFixed>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:60:18 + --> $DIR/enum-variant-generic-args.rs:63:18 | -LL | AliasFixed::<()>::SVariant(()); +LL | AliasFixed::<()>::SVariant { v: () }; | ^^ unexpected type argument -error[E0618]: expected function, found enum variant `<AliasFixed<()>>::SVariant` - --> $DIR/enum-variant-generic-args.rs:60:5 - | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<AliasFixed<()>>::SVariant` defined here -... -LL | AliasFixed::<()>::SVariant(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<AliasFixed<()>>::SVariant` is a unit variant, you need to write it without the parenthesis - | -LL | <AliasFixed<()>>::SVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:62:18 + --> $DIR/enum-variant-generic-args.rs:65:18 | -LL | AliasFixed::<()>::SVariant::<()>(()); +LL | AliasFixed::<()>::SVariant::<()> { v: () }; | ^^ unexpected type argument error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:62:34 + --> $DIR/enum-variant-generic-args.rs:65:34 | -LL | AliasFixed::<()>::SVariant::<()>(()); +LL | AliasFixed::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed -error[E0618]: expected function, found enum variant `<AliasFixed<()>>::SVariant::<()>` - --> $DIR/enum-variant-generic-args.rs:62:5 - | -LL | enum Enum<T> { TSVariant(T), SVariant { v: T } } - | ----------------- `<AliasFixed<()>>::SVariant::<()>` defined here -... -LL | AliasFixed::<()>::SVariant::<()>(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- - | | - | call expression requires function -help: `<AliasFixed<()>>::SVariant::<()>` is a unit variant, you need to write it without the parenthesis - | -LL | <AliasFixed<()>>::SVariant::<()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 30 previous errors +error: aborting due to 25 previous errors -Some errors occurred: E0107, E0109, E0423, E0618. +Some errors occurred: E0107, E0109, E0308. For more information about an error, try `rustc --explain E0107`. From 8fec0076651fa7e149e990947f9ccbbcfb9d3d64 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Thu, 20 Dec 2018 03:26:07 +0000 Subject: [PATCH 023/124] Fixed type inference for tuple struct variants. --- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/mod.rs | 17 +++++++++++------ src/test/run-pass/enum-variant-generic-args.rs | 15 +-------------- src/test/ui/enum-variant-generic-args.rs | 4 ++++ 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 98013dd00dc70..a68148515c425 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1551,7 +1551,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // Case 2. Reference to a variant constructor. Def::Variant(def_id) | Def::VariantCtor(def_id, ..) => { - let adt_def = self_ty.and_then(|t| t.ty_adt_def()); + let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap()); let (generics_def_id, index) = if let Some(adt_def) = adt_def { debug_assert!(adt_def.is_enum()); (adt_def.did, last) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3f9faab58919e..7a4bde1f5c7b3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5077,7 +5077,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def); let mut user_self_ty = None; + let mut is_alias_variant_ctor = false; match def { + Def::VariantCtor(_, _) => { + if let Some(self_ty) = self_ty { + let adt_def = self_ty.ty_adt_def().unwrap(); + user_self_ty = Some(UserSelfTy { + impl_def_id: adt_def.did, + self_ty, + }); + is_alias_variant_ctor = true; + } + } Def::Method(def_id) | Def::AssociatedConst(def_id) => { let container = tcx.associated_item(def_id).container; @@ -5109,12 +5120,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let is_alias_variant_ctor = - match def { - Def::VariantCtor(_, _) if self_ty.is_some() => true, - _ => false, - }; - let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { if !generic_segs.contains(&index) || is_alias_variant_ctor { diff --git a/src/test/run-pass/enum-variant-generic-args.rs b/src/test/run-pass/enum-variant-generic-args.rs index ace4ebdfa0595..0743f99897922 100644 --- a/src/test/run-pass/enum-variant-generic-args.rs +++ b/src/test/run-pass/enum-variant-generic-args.rs @@ -3,6 +3,7 @@ #![allow(irrefutable_let_patterns)] +#[allow(dead_code)] enum Enum<T> { TSVariant(T), SVariant { v: T } } type Alias<T> = Enum<T>; type AliasFixed = Enum<()>; @@ -16,16 +17,6 @@ macro_rules! is_variant { ); } -impl<T> Enum<T> { - fn ts_variant() { - is_variant!(TSVariant, Self::TSVariant(())); - } - - fn s_variant() { - is_variant!(SVariant, Self::SVariant { v: () }); - } -} - fn main() { // Tuple struct variant @@ -38,8 +29,6 @@ fn main() { is_variant!(TSVariant, AliasFixed::TSVariant(())); - Enum::<()>::ts_variant(); - // Struct variant is_variant!(SVariant, Enum::SVariant { v: () }); @@ -50,6 +39,4 @@ fn main() { is_variant!(SVariant, Alias::<()>::SVariant { v: () }); is_variant!(SVariant, AliasFixed::SVariant { v: () }); - - Enum::<()>::s_variant(); } diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs index 044d8438815ba..ad821344e2143 100644 --- a/src/test/ui/enum-variant-generic-args.rs +++ b/src/test/ui/enum-variant-generic-args.rs @@ -6,6 +6,8 @@ type AliasFixed = Enum<()>; impl<T> Enum<T> { fn ts_variant() { + Self::TSVariant(()); + //~^ ERROR type parameters are not allowed on this name [E0109] Self::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::TSVariant(()); @@ -16,6 +18,8 @@ impl<T> Enum<T> { } fn s_variant() { + Self::SVariant { v: () }; + //~^ ERROR type parameters are not allowed on this name [E0109] Self::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR mismatched types [E0308] From 0f3f0b8b2db0021b90e1b77ab753933edc18edbf Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Thu, 20 Dec 2018 18:38:55 +0000 Subject: [PATCH 024/124] Fixed ICE when type arguments are specified on `Self` type. --- src/librustc_typeck/astconv.rs | 8 +- src/librustc_typeck/check/mod.rs | 10 ++- src/test/ui/enum-variant-generic-args.rs | 5 +- src/test/ui/enum-variant-generic-args.stderr | 79 +++++++++++++------- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a68148515c425..f819a5f642fcb 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1431,7 +1431,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } - pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment>>(&self, segments: T) { + pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment>>( + &self, segments: T) -> bool { + let mut has_err = false; for segment in segments { segment.with_generic_args(|generic_args| { let (mut err_for_lt, mut err_for_ty) = (false, false); @@ -1440,6 +1442,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { hir::GenericArg::Lifetime(lt) => { if err_for_lt { continue } err_for_lt = true; + has_err = true; (struct_span_err!(self.tcx().sess, lt.span, E0110, "lifetime arguments are not allowed on this entity"), lt.span, @@ -1448,6 +1451,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { hir::GenericArg::Type(ty) => { if err_for_ty { continue } err_for_ty = true; + has_err = true; (struct_span_err!(self.tcx().sess, ty.span, E0109, "type arguments are not allowed on this entity"), ty.span, @@ -1461,11 +1465,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } } for binding in &generic_args.bindings { + has_err = true; Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); break; } }) } + has_err } pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a4bde1f5c7b3..f61f2f3f49037 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5121,13 +5121,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // errors if type parameters are provided in an inappropriate place. let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); - AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { + let generics_has_err = AstConv::prohibit_generics( + self, segments.iter().enumerate().filter_map(|(index, seg)| { if !generic_segs.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None } })); + if generics_has_err { + // Don't try to infer type parameters when prohibited generic arguments were given. + user_self_ty = None; + } match def { Def::Local(nid) | Def::Upvar(nid, ..) => { @@ -5299,9 +5304,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method` - // is inherent, there is no `Self` parameter, instead, the impl needs + // is inherent, there is no `Self` parameter; instead, the impl needs // type parameters, which we can infer by unifying the provided `Self` // with the substituted impl type. + // This also occurs for an enum variant on a type alias. let ty = tcx.type_of(impl_def_id); let impl_ty = self.instantiate_type_scheme(span, &substs, &ty); diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs index ad821344e2143..6eddd70964546 100644 --- a/src/test/ui/enum-variant-generic-args.rs +++ b/src/test/ui/enum-variant-generic-args.rs @@ -7,11 +7,12 @@ type AliasFixed = Enum<()>; impl<T> Enum<T> { fn ts_variant() { Self::TSVariant(()); - //~^ ERROR type parameters are not allowed on this name [E0109] + //~^ ERROR mismatched types [E0308] Self::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this entity [E0109] Self::<()>::TSVariant(()); //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR mismatched types [E0308] Self::<()>::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR type arguments are not allowed on this entity [E0109] @@ -19,7 +20,7 @@ impl<T> Enum<T> { fn s_variant() { Self::SVariant { v: () }; - //~^ ERROR type parameters are not allowed on this name [E0109] + //~^ ERROR mismatched types [E0308] Self::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this entity [E0109] //~^^ ERROR mismatched types [E0308] diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr index 4228a807bad16..4d3b576734643 100644 --- a/src/test/ui/enum-variant-generic-args.stderr +++ b/src/test/ui/enum-variant-generic-args.stderr @@ -1,35 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:9:25 + | +LL | Self::TSVariant(()); + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:9:27 + --> $DIR/enum-variant-generic-args.rs:11:27 | LL | Self::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:11:16 + --> $DIR/enum-variant-generic-args.rs:13:16 | LL | Self::<()>::TSVariant(()); | ^^ type argument not allowed +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:13:31 + | +LL | Self::<()>::TSVariant(()); + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:13:16 + --> $DIR/enum-variant-generic-args.rs:16:16 | LL | Self::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:13:33 + --> $DIR/enum-variant-generic-args.rs:16:33 | LL | Self::<()>::TSVariant::<()>(()); | ^^ type argument not allowed +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:22:29 + | +LL | Self::SVariant { v: () }; + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:19:26 + --> $DIR/enum-variant-generic-args.rs:24:26 | LL | Self::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0308]: mismatched types - --> $DIR/enum-variant-generic-args.rs:19:35 + --> $DIR/enum-variant-generic-args.rs:24:35 | LL | Self::SVariant::<()> { v: () }; | ^^ expected type parameter, found () @@ -38,13 +65,13 @@ LL | Self::SVariant::<()> { v: () }; found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:22:16 + --> $DIR/enum-variant-generic-args.rs:27:16 | LL | Self::<()>::SVariant { v: () }; | ^^ type argument not allowed error[E0308]: mismatched types - --> $DIR/enum-variant-generic-args.rs:22:35 + --> $DIR/enum-variant-generic-args.rs:27:35 | LL | Self::<()>::SVariant { v: () }; | ^^ expected type parameter, found () @@ -53,19 +80,19 @@ LL | Self::<()>::SVariant { v: () }; found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:25:16 + --> $DIR/enum-variant-generic-args.rs:30:16 | LL | Self::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:25:32 + --> $DIR/enum-variant-generic-args.rs:30:32 | LL | Self::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0308]: mismatched types - --> $DIR/enum-variant-generic-args.rs:25:41 + --> $DIR/enum-variant-generic-args.rs:30:41 | LL | Self::<()>::SVariant::<()> { v: () }; | ^^ expected type parameter, found () @@ -74,90 +101,90 @@ LL | Self::<()>::SVariant::<()> { v: () }; found type `()` error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:35:29 + --> $DIR/enum-variant-generic-args.rs:40:29 | LL | Enum::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:38:24 + --> $DIR/enum-variant-generic-args.rs:43:24 | LL | Alias::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:40:30 + --> $DIR/enum-variant-generic-args.rs:45:30 | LL | Alias::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:43:29 + --> $DIR/enum-variant-generic-args.rs:48:29 | LL | AliasFixed::TSVariant::<()>(()); | ^^ type argument not allowed error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:45:18 + --> $DIR/enum-variant-generic-args.rs:50:18 | LL | AliasFixed::<()>::TSVariant(()); | ^^ unexpected type argument error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:47:18 + --> $DIR/enum-variant-generic-args.rs:52:18 | LL | AliasFixed::<()>::TSVariant::<()>(()); | ^^ unexpected type argument error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:47:35 + --> $DIR/enum-variant-generic-args.rs:52:35 | LL | AliasFixed::<()>::TSVariant::<()>(()); | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:53:28 + --> $DIR/enum-variant-generic-args.rs:58:28 | LL | Enum::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:56:23 + --> $DIR/enum-variant-generic-args.rs:61:23 | LL | Alias::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:58:29 + --> $DIR/enum-variant-generic-args.rs:63:29 | LL | Alias::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:61:28 + --> $DIR/enum-variant-generic-args.rs:66:28 | LL | AliasFixed::SVariant::<()> { v: () }; | ^^ type argument not allowed error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:63:18 + --> $DIR/enum-variant-generic-args.rs:68:18 | LL | AliasFixed::<()>::SVariant { v: () }; | ^^ unexpected type argument error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/enum-variant-generic-args.rs:65:18 + --> $DIR/enum-variant-generic-args.rs:70:18 | LL | AliasFixed::<()>::SVariant::<()> { v: () }; | ^^ unexpected type argument error[E0109]: type arguments are not allowed on this entity - --> $DIR/enum-variant-generic-args.rs:65:34 + --> $DIR/enum-variant-generic-args.rs:70:34 | LL | AliasFixed::<()>::SVariant::<()> { v: () }; | ^^ type argument not allowed -error: aborting due to 25 previous errors +error: aborting due to 28 previous errors Some errors occurred: E0107, E0109, E0308. For more information about an error, try `rustc --explain E0107`. From 66ee7c4fd0cf3bafc819f0ac088443650b3b2bde Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Wed, 26 Dec 2018 00:07:31 +0000 Subject: [PATCH 025/124] Minor clean-up --- src/librustc_typeck/astconv.rs | 22 ++++++++++++---------- src/librustc_typeck/check/method/mod.rs | 7 ++++--- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f819a5f642fcb..80583a5855864 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -569,7 +569,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let has_self = generic_params.has_self; let (_, potential_assoc_types) = Self::check_generic_arg_count( - self.tcx(), + tcx, span, &generic_params, &generic_args, @@ -594,7 +594,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let substs = Self::create_substs_for_generic_args( - self.tcx(), + tcx, def_id, &[][..], self_ty.is_some(), @@ -1293,8 +1293,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(slice::from_ref(item_segment)); // Check if we have an enum variant here. - if let ty::Adt(adt_def, _) = ty.sty { - if adt_def.is_enum() { + match ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { let variant_def = adt_def.variants.iter().find(|vd| { tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) }); @@ -1305,7 +1305,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.check_stability(def.def_id(), Some(ref_id), span); return (ty, def); } - } + }, + _ => (), } // Find the type of the associated item, and the trait where the associated @@ -1339,7 +1340,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => { let ty_str = ty.to_string(); - // Incorrect enum variant + // Incorrect enum variant. let mut err = tcx.sess.struct_span_err( span, &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), @@ -1669,23 +1670,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.mk_ty_param(index, tcx.hir().name(node_id).as_interned_str()) } Def::SelfTy(_, Some(def_id)) => { - // `Self` in impl (we know the concrete type) + // `Self` in impl (we know the concrete type). assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); tcx.at(span).type_of(def_id) } Def::SelfTy(Some(_), None) => { - // `Self` in trait + // `Self` in trait. assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); tcx.mk_self_type() } Def::AssociatedTy(def_id) => { - self.prohibit_generics(&path.segments[..path.segments.len()-2]); + debug_assert!(path.segments.len() >= 2); + self.prohibit_generics(&path.segments[..path.segments.len() - 2]); self.qpath_to_ty(span, opt_self_ty, def_id, - &path.segments[path.segments.len()-2], + &path.segments[path.segments.len() - 2], path.segments.last().unwrap()) } Def::PrimTy(prim_ty) => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 88814ae6a2db9..a039835b88f81 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -372,8 +372,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; // Check if we have an enum variant here. - if let ty::Adt(adt_def, _) = self_ty.sty { - if adt_def.is_enum() { + match self_ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { let variant_def = adt_def.variants.iter().find(|vd| { tcx.hygienic_eq(method_name, vd.ident, adt_def.did) }); @@ -384,7 +384,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.check_stability(def.def_id(), Some(expr_id), span); return Ok(def); } - } + }, + _ => (), } let mode = probe::Mode::Path; From 2445f43efe51319868266b6a5175c136d4b332b9 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Wed, 26 Dec 2018 16:15:42 +0000 Subject: [PATCH 026/124] Minor cosmetic changes --- src/librustc_typeck/check/_match.rs | 6 +++--- src/librustc_typeck/check/mod.rs | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 923be2a76aa66..b66c383edb51e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -275,7 +275,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { PatKind::Tuple(ref elements, ddpos) => { let mut expected_len = elements.len(); if ddpos.is_some() { - // Require known type only when `..` is present + // Require known type only when `..` is present. if let ty::Tuple(ref tys) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); @@ -284,8 +284,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let max_len = cmp::max(expected_len, elements.len()); let element_tys_iter = (0..max_len).map(|_| self.next_ty_var( - // FIXME: MiscVariable for now, obtaining the span and name information - // from all tuple elements isn't trivial. + // FIXME: `MiscVariable` for now -- obtaining the span and name information + // from all tuple elements isn't trivial. TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f61f2f3f49037..39beb2832851b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4618,7 +4618,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { local: &'gcx hir::Local, init: &'gcx hir::Expr) -> Ty<'tcx> { - // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed + // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed // for #42640 (default match binding modes). // // See #44848. @@ -4663,7 +4663,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { - // Don't do all the complex logic below for DeclItem. + // Don't do all the complex logic below for `DeclItem`. match stmt.node { hir::StmtKind::Decl(ref decl, _) => { if let hir::DeclKind::Item(_) = decl.node { @@ -4675,7 +4675,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement"); - // Hide the outer diverging and has_errors flags. + // Hide the outer diverging and `has_errors` flags. let old_diverges = self.diverges.get(); let old_has_errors = self.has_errors.get(); self.diverges.set(Diverges::Maybe); @@ -4687,11 +4687,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::DeclKind::Local(ref l) => { self.check_decl_local(&l); } - hir::DeclKind::Item(_) => {/* ignore for now */} + // Ignore for now. + hir::DeclKind::Item(_) => () } } hir::StmtKind::Expr(ref expr, _) => { - // Check with expected type of () + // Check with expected type of `()`. self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); } hir::StmtKind::Semi(ref expr, _) => { @@ -4699,7 +4700,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - // Combine the diverging and has_error flags. + // Combine the diverging and `has_error` flags. self.diverges.set(self.diverges.get() | old_diverges); self.has_errors.set(self.has_errors.get() | old_has_errors); } From 92e3a3558af382fa066e4328df03d5130ec6cce0 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Wed, 26 Dec 2018 16:38:35 +0000 Subject: [PATCH 027/124] Changed resolution of enum variants to low priority. --- src/librustc_typeck/astconv.rs | 36 +++++++-------- src/librustc_typeck/check/method/mod.rs | 61 +++++++++++++------------ src/test/ui/bogus-tag.stderr | 4 +- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 80583a5855864..1db7141917f98 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1292,28 +1292,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(slice::from_ref(item_segment)); - // Check if we have an enum variant here. - match ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); - } - }, - _ => (), - } - // Find the type of the associated item, and the trait where the associated // item is declared. let bound = match (&ty.sty, ty_path_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { - // `Self` in an impl of a trait -- we have a concrete `self` type and a + // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. let trait_ref = match tcx.impl_trait_ref(impl_def_id) { Some(trait_ref) => trait_ref, @@ -1365,6 +1348,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { return (tcx.types.err, Def::Err); } _ => { + // Check if we have an enum variant. + match ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::Variant(variant_def.did); + tcx.check_stability(def.def_id(), Some(ref_id), span); + return (ty, def); + } + }, + _ => (), + } + // Don't print `TyErr` to the user. if !ty.references_error() { self.report_ambiguous_associated_type(span, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index a039835b88f81..fe5f43e3c01ef 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -371,38 +371,43 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - // Check if we have an enum variant here. - match self_ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(method_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - tcx.check_stability(def.def_id(), Some(expr_id), span); - return Ok(def); + let mode = probe::Mode::Path; + match self.probe_for_name(span, mode, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope) { + Ok(pick) => { + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } - }, - _ => (), - } - let mode = probe::Mode::Path; - let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope)?; + let def = pick.item.def(); + tcx.check_stability(def.def_id(), Some(expr_id), span); - if let Some(import_id) = pick.import_id { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); - } - - let def = pick.item.def(); - tcx.check_stability(def.def_id(), Some(expr_id), span); + Ok(def) + } + Err(err) => { + // Check if we have an enum variant. + match self_ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); + } + }, + _ => (), + } - Ok(def) + Err(err) + } + } } /// Find item with name `item_name` defined in impl/trait `def_id` diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index 1cb5ee9b6305c..3750df841720c 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -1,11 +1,11 @@ error[E0599]: no variant named `Hsl` found for type `Color` in the current scope - --> $DIR/bogus-tag.rs:7:9 + --> $DIR/bogus-tag.rs:7:16 | LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } | ---------- variant `Hsl` not found here ... LL | Color::Hsl(h, s, l) => { println!("hsl"); } - | ^^^^^^^^^^^^^^^^^^^ variant not found in `Color` + | -------^^^--------- variant not found in `Color` error: aborting due to previous error From 21a012a59c928e332bb7cbabbc5d61b4d69c4784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Wed, 26 Dec 2018 20:05:56 -0800 Subject: [PATCH 028/124] Point at correct span for arguments in format strings When a format string has escaped whitespace characters format arguments were shifted by one per each escaped character. Account for these escaped characters when synthesizing the spans. Fix #55155. --- src/libfmt_macros/lib.rs | 7 +++---- src/libsyntax_ext/format.rs | 4 +++- src/test/ui/fmt/format-string-error-2.rs | 2 ++ src/test/ui/fmt/format-string-error-2.stderr | 8 +++++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index fc8325e5915c4..32ae878909f30 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -144,7 +144,7 @@ pub struct Parser<'a> { /// `Some(raw count)` when the string is "raw", used to position spans correctly style: Option<usize>, /// Start and end byte offset of every successfully parsed argument - pub arg_places: Vec<(usize, usize)>, + pub arg_places: Vec<(SpanIndex, SpanIndex)>, /// Characters that need to be shifted skips: Vec<usize>, /// Span offset of the last opening brace seen, used for error reporting @@ -154,7 +154,7 @@ pub struct Parser<'a> { } #[derive(Clone, Copy, Debug)] -pub struct SpanIndex(usize); +pub struct SpanIndex(pub usize); impl SpanIndex { pub fn unwrap(self) -> usize { @@ -166,7 +166,6 @@ impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option<Piece<'a>> { - let raw = self.raw(); if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { @@ -180,7 +179,7 @@ impl<'a> Iterator for Parser<'a> { } else { let arg = self.argument(); if let Some(arg_pos) = self.must_consume('}').map(|end| { - (pos + raw + 1, end + raw + 2) + (self.to_span_index(pos), self.to_span_index(end + 1)) }) { self.arg_places.push(arg_pos); } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 9d29e2b0fb69a..53d9ae22aace5 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -860,7 +860,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } let arg_spans = parser.arg_places.iter() - .map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end)) + .map(|&(parse::SpanIndex(start), parse::SpanIndex(end))| { + fmt.span.from_inner_byte_pos(start, end) + }) .collect(); let mut cx = Context { diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index fd6e41ec6fca7..3c6c15c06bb2a 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -67,4 +67,6 @@ raw { \n asdf} ", asdf=1); //~^^ ERROR invalid format string + println!("\t{}"); + //~^ ERROR 1 positional argument in format string } diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index 0b3f08c1fbe8d..face0bc0f5f68 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -133,5 +133,11 @@ LL | asdf} | = note: if you intended to print `{`, you can escape it using `{{` -error: aborting due to 13 previous errors +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-string-error-2.rs:70:17 + | +LL | println!("/t{}"); + | ^^ + +error: aborting due to 14 previous errors From 936ea7056ce552b9ca369a0b7a4bd0bab83d9748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Wed, 26 Dec 2018 20:18:41 -0800 Subject: [PATCH 029/124] Add span label to unused string formatting argument Fix #55350. --- src/libsyntax_ext/format.rs | 7 ++++- src/test/ui/if/ifmt-bad-arg.stderr | 26 ++++++++++--------- src/test/ui/macros/format-foreign.stderr | 24 ++++++++++------- .../ui/macros/format-unused-lables.stderr | 20 +++++++------- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 53d9ae22aace5..95bb8c886abf2 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -956,13 +956,18 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let mut diag = { if errs_len == 1 { let (sp, msg) = errs.into_iter().next().unwrap(); - cx.ecx.struct_span_err(sp, msg) + let mut diag = cx.ecx.struct_span_err(sp, msg); + diag.span_label(sp, msg); + diag } else { let mut diag = cx.ecx.struct_span_err( errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(), "multiple unused formatting arguments", ); diag.span_label(cx.fmtsp, "multiple missing formatting specifiers"); + for (sp, msg) in errs { + diag.span_label(sp, msg); + } diag } }; diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 3ae8669a7f244..d4153ac94acd1 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -16,7 +16,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:9:20 | LL | format!("{1}", 1); - | ----- ^ + | ----- ^ argument never used | | | formatting specifier missing @@ -80,15 +80,16 @@ error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:32:17 | LL | format!("", 1, 2); //~ ERROR: multiple unused formatting arguments - | -- ^ ^ - | | + | -- ^ ^ argument never used + | | | + | | argument never used | multiple missing formatting specifiers error: argument never used --> $DIR/ifmt-bad-arg.rs:33:22 | LL | format!("{}", 1, 2); //~ ERROR: argument never used - | ---- ^ + | ---- ^ argument never used | | | formatting specifier missing @@ -96,7 +97,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:34:20 | LL | format!("{1}", 1, 2); //~ ERROR: argument never used - | ----- ^ + | ----- ^ argument never used | | | formatting specifier missing @@ -104,7 +105,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:35:26 | LL | format!("{}", 1, foo=2); //~ ERROR: named argument never used - | ---- ^ + | ---- ^ named argument never used | | | formatting specifier missing @@ -112,7 +113,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:36:22 | LL | format!("{foo}", 1, foo=2); //~ ERROR: argument never used - | ------- ^ + | ------- ^ argument never used | | | formatting specifier missing @@ -120,7 +121,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:37:21 | LL | format!("", foo=2); //~ ERROR: named argument never used - | -- ^ + | -- ^ named argument never used | | | formatting specifier missing @@ -128,8 +129,9 @@ error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:38:32 | LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments - | ------- ^ ^ - | | + | ------- ^ ^ named argument never used + | | | + | | named argument never used | multiple missing formatting specifiers error: duplicate argument named `foo` @@ -160,7 +162,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:51 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ------------------- ^ + | ------------------- ^ named argument never used | | | formatting specifier missing @@ -194,7 +196,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:56:27 | LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used - | -- ^^^^^ + | -- ^^^^^ argument never used | | | help: format specifiers use curly braces: `{}` | diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 41c3c9d75c0aa..0b8bfcbdc17ba 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -2,8 +2,10 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:2:30 | LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments - | -------------- ^^^^^^^^ ^^^^^^^ ^ - | | + | -------------- ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` @@ -16,7 +18,7 @@ error: argument never used --> $DIR/format-foreign.rs:3:29 | LL | println!("%1$*2$.*3$f", 123.456); //~ ERROR never used - | ----------- ^^^^^^^ + | ----------- ^^^^^^^ argument never used | | | help: format specifiers use curly braces: `{0:1$.2$}` | @@ -29,8 +31,10 @@ LL | println!(r###"%.*3$s | ______________- LL | | %s!/n LL | | "###, "Hello,", "World", 4); - | | - ^^^^^^^^ ^^^^^^^ ^ - | |____| + | | - ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | | + | | | | argument never used + | |____| argument never used | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` @@ -44,7 +48,7 @@ error: argument never used --> $DIR/format-foreign.rs:12:30 | LL | println!("{} %f", "one", 2.0); //~ ERROR never used - | ------- ^^^ + | ------- ^^^ argument never used | | | formatting specifier missing @@ -52,7 +56,7 @@ error: named argument never used --> $DIR/format-foreign.rs:14:39 | LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used - | ----- ^^^^^ + | ----- ^^^^^ named argument never used | | | help: format specifiers use curly braces: `{NAME}` | @@ -62,8 +66,10 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:15:32 | LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3); - | ---------------- ^ ^ ^ - | | + | ---------------- ^ ^ ^ named argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers | = note: shell formatting not supported; see the documentation for `std::fmt` diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index c94ff2a16714d..0a5e379a4adb4 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -2,8 +2,10 @@ error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:2:22 | LL | println!("Test", 123, 456, 789); - | ------ ^^^ ^^^ ^^^ - | | + | ------ ^^^ ^^^ ^^^ argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers error: multiple unused formatting arguments @@ -12,17 +14,17 @@ error: multiple unused formatting arguments LL | println!("Test2", | ------- multiple missing formatting specifiers LL | 123, //~ ERROR multiple unused formatting arguments - | ^^^ + | ^^^ argument never used LL | 456, - | ^^^ + | ^^^ argument never used LL | 789 - | ^^^ + | ^^^ argument never used error: named argument never used --> $DIR/format-unused-lables.rs:11:35 | LL | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used - | ------------ ^^^^^^ + | ------------ ^^^^^^ named argument never used | | | formatting specifier missing @@ -35,12 +37,12 @@ LL | println!("Some more $STUFF", | | help: format specifiers use curly braces: `{STUFF}` | multiple missing formatting specifiers LL | "woo!", //~ ERROR multiple unused formatting arguments - | ^^^^^^ + | ^^^^^^ argument never used LL | STUFF= LL | "things" - | ^^^^^^^^ + | ^^^^^^^^ named argument never used LL | , UNUSED="args"); - | ^^^^^^ + | ^^^^^^ named argument never used | = note: shell formatting not supported; see the documentation for `std::fmt` From acb04c1261f3a55224e631a43b93b7e7380f47de Mon Sep 17 00:00:00 2001 From: csmoe <csmoe@msn.com> Date: Thu, 27 Dec 2018 17:23:15 +0800 Subject: [PATCH 030/124] retrieve ty info from place_ty describe index with _ --- .../borrow_check/error_reporting.rs | 76 +++++++------------ .../ui/borrowck/borrowck-describe-lvalue.rs | 2 +- .../borrowck-vec-pattern-move-tail.rs | 2 +- src/test/ui/nll/drop-no-may-dangle.rs | 4 +- src/test/ui/use/use-after-move-self.rs | 2 +- 5 files changed, 34 insertions(+), 52 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index b072e464a2998..6a5b5d172bbe4 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -181,38 +181,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - if let Some(ty) = self.retrieve_type_for_place(used_place) { - let needs_note = match ty.sty { - ty::Closure(id, _) => { - let tables = self.infcx.tcx.typeck_tables_of(id); - let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); - let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - - tables.closure_kind_origins().get(hir_id).is_none() - } - _ => true, - }; + let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let needs_note = match ty.sty { + ty::Closure(id, _) => { + let tables = self.infcx.tcx.typeck_tables_of(id); + let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; - - if let Some(ty) = self.retrieve_type_for_place(place) { - let note_msg = match self.describe_place_with_options( - place, - IncludingDowncast(true), - ) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); - } + tables.closure_kind_origins().get(hir_id).is_none() } + _ => true, + }; + + if needs_note { + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + + let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let note_msg = match self.describe_place_with_options( + place, + IncludingDowncast(true), + ) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); } if let Some((_, mut old_err)) = self.move_error_reported @@ -1558,7 +1556,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )?; buf.push_str("["); if self.append_local_to_string(index, buf).is_err() { - buf.push_str(".."); + buf.push_str("_"); } buf.push_str("]"); } @@ -1663,22 +1661,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Retrieve type of a place for the current MIR representation - fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> { - match place { - Place::Local(local) => { - let local = &self.mir.local_decls[*local]; - Some(local.ty) - } - Place::Promoted(ref prom) => Some(prom.1), - Place::Static(ref st) => Some(st.ty), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(_, ty) => Some(ty), - _ => None, - }, - } - } - /// Check if a place is a thread-local static. pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool { if let Place::Static(statik) = place { diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 00ce234d6d5f0..eb622ac10addf 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -260,7 +260,7 @@ fn main() { let x = &mut v; v[0].y; //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed - //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[_].y` because it was mutably borrowed //[mir]~| ERROR cannot use `*v` because it was mutably borrowed drop(x); } diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index 540f9333bc063..e14ecd90d56fb 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -15,7 +15,7 @@ fn main() { println!("t[0]: {}", t[0]); a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) - //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir) + //[cmp]~| ERROR cannot assign to `a[_]` because it is borrowed (Mir) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index e3659a2f2f66f..23f7f6c265e2f 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -17,10 +17,10 @@ fn main() { use_x(*p.value); } else { use_x(22); - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } struct WrapMayNotDangle<T> { diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs index 1337d61a6d8e8..a6f6c45573d0a 100644 --- a/src/test/ui/use/use-after-move-self.rs +++ b/src/test/ui/use/use-after-move-self.rs @@ -7,7 +7,7 @@ struct S { impl S { pub fn foo(self) -> isize { self.bar(); - return *self.x; //~ ERROR use of moved value: `*self.x` + return *self.x; //~ ERROR use of moved value: `self` } pub fn bar(self) {} From fa563d5b145e6dea28efaa9b14ec846ffa1776ab Mon Sep 17 00:00:00 2001 From: Sean Griffin <sean@seantheprogrammer.com> Date: Thu, 27 Dec 2018 08:53:43 -0700 Subject: [PATCH 031/124] Fix typo in pin documentation Affect is a verb, effect is a noun --- src/libcore/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index d8508631bf9c3..e31ac691e3a3c 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -25,7 +25,7 @@ //! values. //! //! However, these restrictions are usually not necessary. Many types are always freely -//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect +//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the effect //! of [`Pin`]. For `T: Unpin`, `Pin<Box<T>>` and `Box<T>` function identically, as do //! `Pin<&mut T>` and `&mut T`. //! From 65819ce6b59fd0381ae3ecd9876fb7b5a2780057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Thu, 27 Dec 2018 11:36:05 -0800 Subject: [PATCH 032/124] Fix span in char documentation --- src/libstd/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 27e720533b2c9..7755d9339e6f5 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -302,7 +302,7 @@ mod prim_never { } /// ```text /// error: character literal may only contain one codepoint: 'é' /// let c = 'é'; -/// ^^^^ +/// ^^^ /// ``` /// /// Another implication of the 4-byte fixed size of a `char` is that From efd19d5e91dd367a4b19c8a46d83fb82b7979008 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott <ian@iandouglasscott.com> Date: Thu, 27 Dec 2018 16:49:12 -0800 Subject: [PATCH 033/124] Update references to closed issue Issue #28979 was closed with a link to #55467. --- .../src/language-features/non-ascii-idents.md | 4 +-- src/libsyntax/feature_gate.rs | 2 +- .../feature-gate-non_ascii_idents.stderr | 26 +++++++++---------- .../local-modularized-tricky-fail-2.stderr | 6 ++--- src/test/ui/utf8_idents.stderr | 8 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index efb5495fe26ac..46957c00bf95c 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -1,8 +1,8 @@ # `non_ascii_idents` -The tracking issue for this feature is: [#28979] +The tracking issue for this feature is: [#55467] -[#28979]: https://github.com/rust-lang/rust/issues/28979 +[#55467]: https://github.com/rust-lang/rust/issues/55467 ------------------------ diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0eeef969e3524..3f2122e24a642 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -111,7 +111,7 @@ declare_features! ( (active, concat_idents, "1.0.0", Some(29599), None), (active, link_args, "1.0.0", Some(29596), None), (active, log_syntax, "1.0.0", Some(29598), None), - (active, non_ascii_idents, "1.0.0", Some(28979), None), + (active, non_ascii_idents, "1.0.0", Some(55467), None), (active, plugin_registrar, "1.0.0", Some(29597), None), (active, thread_local, "1.0.0", Some(29594), None), (active, trace_macros, "1.0.0", Some(29598), None), diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr index 452a3ecfacd84..5c441189ea7cb 100644 --- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:1:22 | LL | extern crate core as bäz; //~ ERROR non-ascii idents @@ -6,7 +6,7 @@ LL | extern crate core as bäz; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:3:5 | LL | use föö::bar; //~ ERROR non-ascii idents @@ -14,7 +14,7 @@ LL | use föö::bar; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:5:5 | LL | mod föö { //~ ERROR non-ascii idents @@ -22,7 +22,7 @@ LL | mod föö { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:9:4 | LL | fn bär( //~ ERROR non-ascii idents @@ -30,7 +30,7 @@ LL | fn bär( //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:10:5 | LL | bäz: isize //~ ERROR non-ascii idents @@ -38,7 +38,7 @@ LL | bäz: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:12:9 | LL | let _ö: isize; //~ ERROR non-ascii idents @@ -46,7 +46,7 @@ LL | let _ö: isize; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:15:10 | LL | (_ä, _) => {} //~ ERROR non-ascii idents @@ -54,7 +54,7 @@ LL | (_ä, _) => {} //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:19:8 | LL | struct Föö { //~ ERROR non-ascii idents @@ -62,7 +62,7 @@ LL | struct Föö { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:20:5 | LL | föö: isize //~ ERROR non-ascii idents @@ -70,7 +70,7 @@ LL | föö: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:23:6 | LL | enum Bär { //~ ERROR non-ascii idents @@ -78,7 +78,7 @@ LL | enum Bär { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:24:5 | LL | Bäz { //~ ERROR non-ascii idents @@ -86,7 +86,7 @@ LL | Bäz { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:25:9 | LL | qüx: isize //~ ERROR non-ascii idents @@ -94,7 +94,7 @@ LL | qüx: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:30:8 | LL | fn qüx(); //~ ERROR non-ascii idents diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr index 42ee68073fbc5..40cb10ced16f5 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:20:32 | LL | exported!(); @@ -9,7 +9,7 @@ LL | () => ( struct Б; ) //~ ERROR non-ascii idents are not ful | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:36:24 | LL | panic!(); @@ -20,7 +20,7 @@ LL | () => ( struct Г; ) //~ ERROR non-ascii idents are not fully suppo | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:46:24 | LL | include!(); diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr index 4279ed78d39f9..b1bb4a3001557 100644 --- a/src/test/ui/utf8_idents.stderr +++ b/src/test/ui/utf8_idents.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:4:5 | LL | 'β, //~ ERROR non-ascii idents are not fully supported @@ -6,7 +6,7 @@ LL | 'β, //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:5:5 | LL | γ //~ ERROR non-ascii idents are not fully supported @@ -14,7 +14,7 @@ LL | γ //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:9:5 | LL | δ: usize //~ ERROR non-ascii idents are not fully supported @@ -22,7 +22,7 @@ LL | δ: usize //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:13:9 | LL | let α = 0.00001f64; //~ ERROR non-ascii idents are not fully supported From 375165418cf51635e81a28cbd14dfacc8198d682 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Fri, 28 Dec 2018 05:20:11 +0300 Subject: [PATCH 034/124] resolve: Fix an ICE in import validation --- src/librustc_resolve/resolve_imports.rs | 18 ++++++++++++------ .../uniform-paths/auxiliary/issue-56596.rs | 1 + .../ui/rust-2018/uniform-paths/issue-56596.rs | 14 ++++++++++++++ .../rust-2018/uniform-paths/issue-56596.stderr | 18 ++++++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-56596.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-56596.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9a7b8c24993c6..5830aa3713d83 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -223,11 +223,6 @@ impl<'a> Resolver<'a> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { - if let Some(blacklisted_binding) = this.blacklisted_binding { - if ptr::eq(binding, blacklisted_binding) { - return Err((Determined, Weak::No)); - } - } // `extern crate` are always usable for backwards compatibility, see issue #37020, // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`. let usable = this.is_accessible(binding.vis) || binding.is_extern_crate(); @@ -235,7 +230,18 @@ impl<'a> Resolver<'a> { }; if record_used { - return resolution.binding.ok_or((Determined, Weak::No)).and_then(|binding| { + return resolution.binding.and_then(|binding| { + // If the primary binding is blacklisted, search further and return the shadowed + // glob binding if it exists. What we really want here is having two separate + // scopes in a module - one for non-globs and one for globs, but until that's done + // use this hack to avoid inconsistent resolution ICEs during import validation. + if let Some(blacklisted_binding) = self.blacklisted_binding { + if ptr::eq(binding, blacklisted_binding) { + return resolution.shadowed_glob; + } + } + Some(binding) + }).ok_or((Determined, Weak::No)).and_then(|binding| { if self.last_import_segment && check_usable(self, binding).is_err() { Err((Determined, Weak::No)) } else { diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs new file mode 100644 index 0000000000000..bc010a3dd2ba0 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs @@ -0,0 +1 @@ +// Nothing here diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs new file mode 100644 index 0000000000000..5c40d78d81c29 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs @@ -0,0 +1,14 @@ +// edition:2018 +// compile-flags: --extern issue_56596 +// aux-build:issue-56596.rs + +#![feature(uniform_paths)] + +mod m { + pub mod issue_56596 {} +} + +use m::*; +use issue_56596; //~ ERROR `issue_56596` is ambiguous + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr new file mode 100644 index 0000000000000..293d0ec6a7208 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr @@ -0,0 +1,18 @@ +error[E0659]: `issue_56596` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-56596.rs:12:5 + | +LL | use issue_56596; //~ ERROR `issue_56596` is ambiguous + | ^^^^^^^^^^^ ambiguous name + | + = note: `issue_56596` could refer to an extern crate passed with `--extern` + = help: use `::issue_56596` to refer to this extern crate unambiguously +note: `issue_56596` could also refer to the module imported here + --> $DIR/issue-56596.rs:11:5 + | +LL | use m::*; + | ^^^^ + = help: use `crate::issue_56596` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. From b4d18a2321a32b8b39802c0fc8d156b3ec1979a3 Mon Sep 17 00:00:00 2001 From: John Heitmann <jheitmann@gmail.com> Date: Thu, 27 Dec 2018 22:26:54 -0800 Subject: [PATCH 035/124] Give the crate select chevron room to breathe. --- src/librustdoc/html/static/down-arrow.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/down-arrow.svg b/src/librustdoc/html/static/down-arrow.svg index a2d9a37dde091..c0f59f0c36fce 100644 --- a/src/librustdoc/html/static/down-arrow.svg +++ b/src/librustdoc/html/static/down-arrow.svg @@ -1 +1 @@ -<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="128px" id="Layer_1" style="enable-background:new 0 0 128 128;" version="1.1" viewBox="0 0 128 128" width="128px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="111" x2="64" y1="40.5" y2="87.499"/><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="64" x2="17" y1="87.499" y2="40.5"/></g></svg> \ No newline at end of file +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="128px" id="Layer_1" style="enable-background:new 0 0 128 128;" version="1.1" viewBox="-30 -20 176 176" width="128px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="111" x2="64" y1="40.5" y2="87.499"/><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="64" x2="17" y1="87.499" y2="40.5"/></g></svg> \ No newline at end of file From 2cb1ece942e8d90a64d8926ddc48393a6623ca4d Mon Sep 17 00:00:00 2001 From: kennytm <kennytm@gmail.com> Date: Fri, 28 Dec 2018 22:00:33 +0800 Subject: [PATCH 036/124] Removed aligned ZST requirement from docs of read_/write_unaligned. This is just a copy-paste error. --- src/libcore/ptr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index b9420f32a9492..55a72d7a9a94d 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -591,7 +591,7 @@ pub unsafe fn read<T>(src: *const T) -> T { /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. /// -/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// Note that even if `T` has size `0`, the pointer must be non-NULL. /// /// [`Copy`]: ../marker/trait.Copy.html /// [`read`]: ./fn.read.html @@ -759,7 +759,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// /// * `dst` must be [valid] for writes. /// -/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// Note that even if `T` has size `0`, the pointer must be non-NULL. /// /// [valid]: ../ptr/index.html#safety /// From 6a3d95ebcb428b6f891c959120013a9f8afd8328 Mon Sep 17 00:00:00 2001 From: Lin Clark <lclark@mozilla.com> Date: Fri, 28 Dec 2018 13:34:00 -0500 Subject: [PATCH 037/124] Update link to rustc guide --- src/librustc_borrowck/borrowck/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index a05c56e3629a3..6c47e8784e025 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -3,7 +3,7 @@ > WARNING: This README is more or less obsolete, and will be removed > soon! The new system is described in the [rustc guide]. -[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html This pass has the job of enforcing memory safety. This is a subtle topic. This docs aim to explain both the practice and the theory From 00ef955415105ac595c883997010620046f01986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Thu, 27 Dec 2018 17:04:58 -0800 Subject: [PATCH 038/124] Suggest `.as_ref()` when appropriate for `Option` and `Result` --- src/librustc/infer/error_reporting/mod.rs | 74 +++++++++++++++++++++ src/test/ui/as-ref.stderr | 47 ------------- src/test/ui/{ => suggestions}/as-ref.rs | 10 +++ src/test/ui/suggestions/as-ref.stderr | 81 +++++++++++++++++++++++ 4 files changed, 165 insertions(+), 47 deletions(-) delete mode 100644 src/test/ui/as-ref.stderr rename src/test/ui/{ => suggestions}/as-ref.rs (52%) create mode 100644 src/test/ui/suggestions/as-ref.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 75407835a1b55..c9fc896b1b2d4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -956,6 +956,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diag.span_label(span, message); } } + self.suggest_as_ref_where_appropriate(span, &exp_found, diag); } diag.note_expected_found(&"type", expected, found); @@ -972,6 +973,79 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.note_error_origin(diag, &cause); } + /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate, + /// suggest it. + fn suggest_as_ref_where_appropriate( + &self, + span: Span, + exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, + diag: &mut DiagnosticBuilder<'tcx>, + ) { + match (&exp_found.expected.sty, &exp_found.found.sty) { + (TyKind::Adt(exp_def, exp_substs), TyKind::Ref(_, found_ty, _)) => { + if let TyKind::Adt(found_def, found_substs) = found_ty.sty { + let path_str = format!("{:?}", exp_def); + if exp_def == &found_def { + let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \ + `.as_ref()`"; + let result_msg = "you can convert from `&Result<T, E>` to \ + `Result<&T, &E>` using `.as_ref()`"; + let have_as_ref = &[ + ("std::option::Option", opt_msg), + ("core::option::Option", opt_msg), + ("std::result::Result", result_msg), + ("core::result::Result", result_msg), + ]; + if let Some(msg) = have_as_ref.iter() + .filter_map(|(path, msg)| if &path_str == path { + Some(msg) + } else { + None + }).next() + { + let mut show_suggestion = true; + for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { + if let TyKind::Ref(_, exp_ty, _) = exp_ty.sty { + match (&exp_ty.sty, &found_ty.sty) { + (TyKind::Adt(exp_did, _), TyKind::Adt(found_did, _)) + if exp_did == found_did => {} + (TyKind::Bool, TyKind::Bool) | + (TyKind::Char, TyKind::Char) | + (TyKind::Str, TyKind::Str) | + (_, TyKind::Param(_)) | + (_, TyKind::Infer(_)) | + (TyKind::Param(_), _) | + (TyKind::Infer(_), _) => {} + (TyKind::Int(x), TyKind::Int(y)) if x == y => {} + (TyKind::Uint(x), TyKind::Uint(y)) if x == y => {} + (TyKind::Int(x), TyKind::Int(y)) if x == y => {} + (TyKind::Uint(x), TyKind::Uint(y)) if x == y => {} + (TyKind::Float(x), TyKind::Float(y)) if x == y => {} + _ => show_suggestion = false, + } + } else { + show_suggestion = false; + } + } + if let (Ok(snippet), true) = ( + self.tcx.sess.source_map().span_to_snippet(span), + show_suggestion, + ) { + diag.span_suggestion_with_applicability( + span, + msg, + format!("{}.as_ref()", snippet), + Applicability::MachineApplicable, + ); + } + } + } + } + } + _ => {} + } + } + pub fn report_and_explain_type_error( &self, trace: TypeTrace<'tcx>, diff --git a/src/test/ui/as-ref.stderr b/src/test/ui/as-ref.stderr deleted file mode 100644 index 8ca54e8006cf3..0000000000000 --- a/src/test/ui/as-ref.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/as-ref.rs:6:27 - | -LL | opt.map(|arg| takes_ref(arg)); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:8:37 - | -LL | opt.and_then(|arg| Some(takes_ref(arg))); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:11:27 - | -LL | opt.map(|arg| takes_ref(arg)); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:13:35 - | -LL | opt.and_then(|arg| Ok(takes_ref(arg))); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/as-ref.rs b/src/test/ui/suggestions/as-ref.rs similarity index 52% rename from src/test/ui/as-ref.rs rename to src/test/ui/suggestions/as-ref.rs index 822d10f2ca7b3..03f04c389f1f3 100644 --- a/src/test/ui/as-ref.rs +++ b/src/test/ui/suggestions/as-ref.rs @@ -12,4 +12,14 @@ fn main() { //~^ ERROR mismatched types [E0308] opt.and_then(|arg| Ok(takes_ref(arg))); //~^ ERROR mismatched types [E0308] + let x: &Option<usize> = &Some(3); + let y: Option<&usize> = x; + //~^ ERROR mismatched types [E0308] + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, &usize> = x; + //~^ ERROR mismatched types [E0308] + // note: do not suggest because of `E: usize` + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, usize> = x; + //~^ ERROR mismatched types [E0308] } diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr new file mode 100644 index 0000000000000..7273496a7ce06 --- /dev/null +++ b/src/test/ui/suggestions/as-ref.stderr @@ -0,0 +1,81 @@ +error[E0308]: mismatched types + --> $DIR/as-ref.rs:6:27 + | +LL | opt.map(|arg| takes_ref(arg)); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:8:37 + | +LL | opt.and_then(|arg| Some(takes_ref(arg))); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:11:27 + | +LL | opt.map(|arg| takes_ref(arg)); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:13:35 + | +LL | opt.and_then(|arg| Ok(takes_ref(arg))); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:16:27 + | +LL | let y: Option<&usize> = x; + | ^ + | | + | expected enum `std::option::Option`, found reference + | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()` + | + = note: expected type `std::option::Option<&usize>` + found type `&std::option::Option<usize>` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:19:35 + | +LL | let y: Result<&usize, &usize> = x; + | ^ expected enum `std::result::Result`, found reference + | + = note: expected type `std::result::Result<&usize, &usize>` + found type `&std::result::Result<usize, usize>` +help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()` + | +LL | let y: Result<&usize, &usize> = x.as_ref(); + | ^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:23:34 + | +LL | let y: Result<&usize, usize> = x; + | ^ expected enum `std::result::Result`, found reference + | + = note: expected type `std::result::Result<&usize, usize>` + found type `&std::result::Result<usize, usize>` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. From e3db7ee5b5edce793a0921d019d5b5038ff3c276 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Fri, 21 Dec 2018 14:15:47 +0000 Subject: [PATCH 039/124] Clarify wording of E0512 --- src/librustc/diagnostics.rs | 3 +- src/librustc/middle/intrinsicck.rs | 15 ++++---- src/test/ui/error-codes/E0512.stderr | 6 ++-- src/test/ui/issues/issue-21174.rs | 2 +- src/test/ui/issues/issue-21174.stderr | 6 ++-- src/test/ui/issues/issue-28625.rs | 2 +- src/test/ui/issues/issue-28625.stderr | 8 ++--- src/test/ui/issues/issue-32377.rs | 2 +- src/test/ui/issues/issue-32377.stderr | 6 ++-- .../packed-struct-generic-transmute.rs | 2 +- .../packed-struct-generic-transmute.stderr | 6 ++-- .../packed-struct/packed-struct-transmute.rs | 2 +- .../packed-struct-transmute.stderr | 6 ++-- src/test/ui/transmute/main.rs | 8 ++--- src/test/ui/transmute/main.stderr | 32 ++++++++--------- .../ui/transmute/transmute-different-sizes.rs | 6 ++-- .../transmute-different-sizes.stderr | 18 +++++----- .../ui/transmute/transmute-fat-pointers.rs | 8 ++--- .../transmute/transmute-fat-pointers.stderr | 32 ++++++++--------- .../transmute-from-fn-item-types-error.rs | 4 +-- .../transmute-from-fn-item-types-error.stderr | 12 +++---- src/test/ui/transmute/transmute-impl.rs | 2 +- src/test/ui/transmute/transmute-impl.stderr | 8 ++--- .../ui/transmute/transmute-type-parameters.rs | 12 +++---- .../transmute-type-parameters.stderr | 36 +++++++++---------- 25 files changed, 123 insertions(+), 121 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index d073a4dd0c9c2..4bc52e82f9be1 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1552,7 +1552,8 @@ fn takes_u8(_: u8) {} fn main() { unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: transmute called with types of different sizes + // error: cannot transmute between types of different sizes, + // or dependently-sized types } ``` diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 2010926ede5e6..e9f310b05ac77 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -97,11 +97,11 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { format!("{} bits", size.bits()) } Ok(SizeSkeleton::Pointer { tail, .. }) => { - format!("pointer to {}", tail) + format!("pointer to `{}`", tail) } Err(LayoutError::Unknown(bad)) => { if bad == ty { - "this type's size can vary".to_owned() + "this type does not have a fixed size".to_owned() } else { format!("size can vary because of {}", bad) } @@ -110,11 +110,12 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { } }; - struct_span_err!(self.tcx.sess, span, E0512, - "transmute called with types of different sizes") - .note(&format!("source type: {} ({})", from, skeleton_string(from, sk_from))) - .note(&format!("target type: {} ({})", to, skeleton_string(to, sk_to))) - .emit(); + let mut err = struct_span_err!(self.tcx.sess, span, E0512, + "cannot transmute between types of different sizes, \ + or dependently-sized types"); + err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) + .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + err.emit() } } diff --git a/src/test/ui/error-codes/E0512.stderr b/src/test/ui/error-codes/E0512.stderr index 5b07afc29190c..998f6403f0b29 100644 --- a/src/test/ui/error-codes/E0512.stderr +++ b/src/test/ui/error-codes/E0512.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/E0512.rs:4:23 | LL | unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 | ^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: u16 (16 bits) - = note: target type: u8 (8 bits) + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21174.rs b/src/test/ui/issues/issue-21174.rs index 4f835cde641e7..07827425116af 100644 --- a/src/test/ui/issues/issue-21174.rs +++ b/src/test/ui/issues/issue-21174.rs @@ -5,7 +5,7 @@ trait Trait<'a> { fn foo<'a, T: Trait<'a>>(value: T::A) { let new: T::B = unsafe { std::mem::transmute(value) }; -//~^ ERROR: transmute called with types of different sizes +//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types } fn main() { } diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 5ff72aef550c3..5ac5a8665bc69 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-21174.rs:7:30 | LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: <T as Trait<'a>>::A (size can vary because of <T as Trait>::A) - = note: target type: <T as Trait<'a>>::B (size can vary because of <T as Trait>::B) + = note: source type: `<T as Trait<'a>>::A` (size can vary because of <T as Trait>::A) + = note: target type: `<T as Trait<'a>>::B` (size can vary because of <T as Trait>::B) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28625.rs b/src/test/ui/issues/issue-28625.rs index 46cbb45e97bb6..15a6a63d5ef0b 100644 --- a/src/test/ui/issues/issue-28625.rs +++ b/src/test/ui/issues/issue-28625.rs @@ -9,7 +9,7 @@ struct ArrayPeano<T: Bar> { } fn foo<T>(a: &ArrayPeano<T>) -> &[T] where T: Bar { - unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes + unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes } impl Bar for () { diff --git a/src/test/ui/issues/issue-28625.stderr b/src/test/ui/issues/issue-28625.stderr index ae383b44511bd..36cb47944f234 100644 --- a/src/test/ui/issues/issue-28625.stderr +++ b/src/test/ui/issues/issue-28625.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-28625.rs:12:14 | -LL | unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes +LL | unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: &ArrayPeano<T> (N bits) - = note: target type: &[T] (N bits) + = note: source type: `&ArrayPeano<T>` (N bits) + = note: target type: `&[T]` (N bits) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32377.rs b/src/test/ui/issues/issue-32377.rs index 6f073bcce6108..555f6abd791ac 100644 --- a/src/test/ui/issues/issue-32377.rs +++ b/src/test/ui/issues/issue-32377.rs @@ -13,7 +13,7 @@ struct Bar<U: Foo> { fn foo<U: Foo>(x: [usize; 2]) -> Bar<U> { unsafe { mem::transmute(x) } - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/issues/issue-32377.stderr b/src/test/ui/issues/issue-32377.stderr index 72d94721d887f..5e870eb3e8d17 100644 --- a/src/test/ui/issues/issue-32377.stderr +++ b/src/test/ui/issues/issue-32377.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-32377.rs:15:14 | LL | unsafe { mem::transmute(x) } | ^^^^^^^^^^^^^^ | - = note: source type: [usize; 2] (N bits) - = note: target type: Bar<U> (N bits) + = note: source type: `[usize; 2]` (N bits) + = note: target type: `Bar<U>` (N bits) error: aborting due to previous error diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.rs b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs index a2502a53c9d38..c6264b6d2b32e 100644 --- a/src/test/ui/packed-struct/packed-struct-generic-transmute.rs +++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs @@ -3,7 +3,7 @@ // the error points to the start of the file, not the line with the // transmute -// error-pattern: transmute called with types of different sizes +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types use std::mem; diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr index b66cb039b802c..744c832dbb407 100644 --- a/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr +++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/packed-struct-generic-transmute.rs:24:38 | LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo); | ^^^^^^^^^^^^^^ | - = note: source type: Foo<[u8; 5], i32> (72 bits) - = note: target type: Oof<[u8; 5], i32> (96 bits) + = note: source type: `Foo<[u8; 5], i32>` (72 bits) + = note: target type: `Oof<[u8; 5], i32>` (96 bits) error: aborting due to previous error diff --git a/src/test/ui/packed-struct/packed-struct-transmute.rs b/src/test/ui/packed-struct/packed-struct-transmute.rs index 3d1580004b80b..a7d284025d7a0 100644 --- a/src/test/ui/packed-struct/packed-struct-transmute.rs +++ b/src/test/ui/packed-struct/packed-struct-transmute.rs @@ -4,7 +4,7 @@ // transmute // normalize-stderr-test "\d+ bits" -> "N bits" -// error-pattern: transmute called with types of different sizes +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types use std::mem; diff --git a/src/test/ui/packed-struct/packed-struct-transmute.stderr b/src/test/ui/packed-struct/packed-struct-transmute.stderr index d1fb443f310ec..80a8919f77b38 100644 --- a/src/test/ui/packed-struct/packed-struct-transmute.stderr +++ b/src/test/ui/packed-struct/packed-struct-transmute.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/packed-struct-transmute.rs:26:24 | LL | let oof: Oof = mem::transmute(foo); | ^^^^^^^^^^^^^^ | - = note: source type: Foo (N bits) - = note: target type: Oof (N bits) + = note: source type: `Foo` (N bits) + = note: target type: `Oof` (N bits) error: aborting due to previous error diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index 6c6fa47a50d6a..dbad10c1c1980 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -13,20 +13,20 @@ pub trait TypeConstructor<'a> { unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T) -> <C as TypeConstructor<'b>>::T where for<'z> C: TypeConstructor<'z> { - transmute(x) //~ ERROR transmute called with types of different sizes + transmute(x) //~ ERROR cannot transmute between types of different sizes } unsafe fn sizes() { - let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes + let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes } unsafe fn ptrs() { - let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes + let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes } union Foo { x: () } unsafe fn vary() { - let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes + let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes } fn main() {} diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index 9a344747e8fce..a152268c6d8f0 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -1,38 +1,38 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:16:5 | -LL | transmute(x) //~ ERROR transmute called with types of different sizes +LL | transmute(x) //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: <C as TypeConstructor<'a>>::T (size can vary because of <C as TypeConstructor>::T) - = note: target type: <C as TypeConstructor<'b>>::T (size can vary because of <C as TypeConstructor>::T) + = note: source type: `<C as TypeConstructor<'a>>::T` (size can vary because of <C as TypeConstructor>::T) + = note: target type: `<C as TypeConstructor<'b>>::T` (size can vary because of <C as TypeConstructor>::T) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:20:17 | -LL | let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes +LL | let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: u16 (16 bits) - = note: target type: u8 (8 bits) + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:24:17 | -LL | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes +LL | let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &str ($STR bits) - = note: target type: u8 (8 bits) + = note: source type: `&str` (128 bits) + = note: target type: `u8` (8 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:29:18 | -LL | let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes +LL | let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: i32 (32 bits) - = note: target type: Foo (0 bits) + = note: source type: `i32` (32 bits) + = note: target type: `Foo` (0 bits) error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-different-sizes.rs b/src/test/ui/transmute/transmute-different-sizes.rs index 00bdd8c0230ac..690decf639285 100644 --- a/src/test/ui/transmute/transmute-different-sizes.rs +++ b/src/test/ui/transmute/transmute-different-sizes.rs @@ -9,12 +9,12 @@ use std::mem::transmute; unsafe fn f() { let _: i8 = transmute(16i16); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn g<T>(x: &T) { let _: i8 = transmute(x); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } trait Specializable { type Output; } @@ -25,7 +25,7 @@ impl<T> Specializable for T { unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output { transmute(x) - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/transmute/transmute-different-sizes.stderr b/src/test/ui/transmute/transmute-different-sizes.stderr index 3fb9300c1348a..07a38df6973a1 100644 --- a/src/test/ui/transmute/transmute-different-sizes.stderr +++ b/src/test/ui/transmute/transmute-different-sizes.stderr @@ -1,29 +1,29 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:11:17 | LL | let _: i8 = transmute(16i16); | ^^^^^^^^^ | - = note: source type: i16 (N bits) - = note: target type: i8 (N bits) + = note: source type: `i16` (N bits) + = note: target type: `i8` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:16:17 | LL | let _: i8 = transmute(x); | ^^^^^^^^^ | - = note: source type: &T (N bits) - = note: target type: i8 (N bits) + = note: source type: `&T` (N bits) + = note: target type: `i8` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:27:5 | LL | transmute(x) | ^^^^^^^^^ | - = note: source type: u16 (N bits) - = note: target type: <T as Specializable>::Output (this type's size can vary) + = note: source type: `u16` (N bits) + = note: target type: `<T as Specializable>::Output` (this type does not have a fixed size) error: aborting due to 3 previous errors diff --git a/src/test/ui/transmute/transmute-fat-pointers.rs b/src/test/ui/transmute/transmute-fat-pointers.rs index f9385ef8994b2..7c1beffd14ed4 100644 --- a/src/test/ui/transmute/transmute-fat-pointers.rs +++ b/src/test/ui/transmute/transmute-fat-pointers.rs @@ -7,11 +7,11 @@ use std::mem::transmute; fn a<T, U: ?Sized>(x: &[T]) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn c<T, U>(x: &T) -> &U { @@ -23,11 +23,11 @@ fn d<T, U>(x: &[T]) -> &[U] { } fn e<T: ?Sized, U>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn f<T, U: ?Sized>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn main() { } diff --git a/src/test/ui/transmute/transmute-fat-pointers.stderr b/src/test/ui/transmute/transmute-fat-pointers.stderr index aed89ab84ca72..4b34950881a48 100644 --- a/src/test/ui/transmute/transmute-fat-pointers.stderr +++ b/src/test/ui/transmute/transmute-fat-pointers.stderr @@ -1,38 +1,38 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:10:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &[T] (N bits) - = note: target type: &U (pointer to U) + = note: source type: `&[T]` (N bits) + = note: target type: `&U` (pointer to `U`) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:14:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &U (pointer to U) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (pointer to `U`) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:26:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &U (N bits) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:30:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (N bits) - = note: target type: &U (pointer to U) + = note: source type: `&T` (N bits) + = note: target type: `&U` (pointer to `U`) error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs index b06751f376e90..f858a199e48e3 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs @@ -2,7 +2,7 @@ use std::mem; unsafe fn foo() -> (i8, *const (), Option<fn()>) { let i = mem::transmute(bar); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types let p = mem::transmute(foo); @@ -19,7 +19,7 @@ unsafe fn foo() -> (i8, *const (), Option<fn()>) { unsafe fn bar() { // Error as usual if the resulting type is not pointer-sized. mem::transmute::<_, u8>(main); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types mem::transmute::<_, *mut ()>(foo); diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 07e8c60e91e16..d08078bcfbaea 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-from-fn-item-types-error.rs:4:13 | LL | let i = mem::transmute(bar); | ^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() {bar} (0 bits) - = note: target type: i8 (8 bits) + = note: source type: `unsafe fn() {bar}` (0 bits) + = note: target type: `i8` (8 bits) error[E0591]: can't transmute zero-sized type --> $DIR/transmute-from-fn-item-types-error.rs:8:13 @@ -27,14 +27,14 @@ LL | let of = mem::transmute(main); = note: target type: std::option::Option<fn()> = help: cast with `as` to a pointer instead -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-from-fn-item-types-error.rs:21:5 | LL | mem::transmute::<_, u8>(main); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: fn() {main} (0 bits) - = note: target type: u8 (8 bits) + = note: source type: `fn() {main}` (0 bits) + = note: target type: `u8` (8 bits) error[E0591]: can't transmute zero-sized type --> $DIR/transmute-from-fn-item-types-error.rs:25:5 diff --git a/src/test/ui/transmute/transmute-impl.rs b/src/test/ui/transmute/transmute-impl.rs index 23fddfe038e29..df422bda166c1 100644 --- a/src/test/ui/transmute/transmute-impl.rs +++ b/src/test/ui/transmute/transmute-impl.rs @@ -18,7 +18,7 @@ impl<T: ?Sized> Foo<T> { fn n(x: &T) -> &isize { // Not OK here, because T : Sized is not in scope. - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } } diff --git a/src/test/ui/transmute/transmute-impl.stderr b/src/test/ui/transmute/transmute-impl.stderr index ad46c24e9c6c1..8acc0aaf3ab52 100644 --- a/src/test/ui/transmute/transmute-impl.stderr +++ b/src/test/ui/transmute/transmute-impl.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-impl.rs:21:18 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &isize (N bits) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&isize` (N bits) error: aborting due to previous error diff --git a/src/test/ui/transmute/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs index 812386cf1653a..5f44b2d0f0163 100644 --- a/src/test/ui/transmute/transmute-type-parameters.rs +++ b/src/test/ui/transmute/transmute-type-parameters.rs @@ -4,17 +4,17 @@ use std::mem::transmute; unsafe fn f<T>(x: T) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn g<T>(x: (T, i32)) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn h<T>(x: [T; 10]) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } struct Bad<T> { @@ -23,7 +23,7 @@ struct Bad<T> { unsafe fn i<T>(x: Bad<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } enum Worse<T> { @@ -33,12 +33,12 @@ enum Worse<T> { unsafe fn j<T>(x: Worse<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn k<T>(x: Option<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr index c7cdf31dcd56c..a355a1bf31833 100644 --- a/src/test/ui/transmute/transmute-type-parameters.stderr +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -1,56 +1,56 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:6:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: T (this type's size can vary) - = note: target type: i32 (32 bits) + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:11:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: (T, i32) (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `(T, i32)` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:16:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: [T; 10] (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `[T; 10]` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:25:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: Bad<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `Bad<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:35:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: Worse<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `Worse<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:40:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: std::option::Option<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `std::option::Option<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) error: aborting due to 6 previous errors From 9e15f426fcfe81c19804eb580b400e7b9988f35f Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Fri, 21 Dec 2018 14:23:28 +0000 Subject: [PATCH 040/124] Add specific diagnostic for transmuting between equal associated types --- src/librustc/middle/intrinsicck.rs | 4 ++++ src/test/ui/transmute-equal-assoc-types.rs | 9 +++++++++ src/test/ui/transmute-equal-assoc-types.stderr | 11 +++++++++++ 3 files changed, 24 insertions(+) create mode 100644 src/test/ui/transmute-equal-assoc-types.rs create mode 100644 src/test/ui/transmute-equal-assoc-types.stderr diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index e9f310b05ac77..1716daaa107c4 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -113,8 +113,12 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, span, E0512, "cannot transmute between types of different sizes, \ or dependently-sized types"); + if from == to { + err.note(&format!("`{}` does not have a fixed size", from)); + } else { err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + } err.emit() } } diff --git a/src/test/ui/transmute-equal-assoc-types.rs b/src/test/ui/transmute-equal-assoc-types.rs new file mode 100644 index 0000000000000..6f357543e5c44 --- /dev/null +++ b/src/test/ui/transmute-equal-assoc-types.rs @@ -0,0 +1,9 @@ +trait Foo { + type Bar; +} + +unsafe fn noop<F: Foo>(foo: F::Bar) -> F::Bar { + ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes +} + +fn main() {} diff --git a/src/test/ui/transmute-equal-assoc-types.stderr b/src/test/ui/transmute-equal-assoc-types.stderr new file mode 100644 index 0000000000000..46bbf1c185889 --- /dev/null +++ b/src/test/ui/transmute-equal-assoc-types.stderr @@ -0,0 +1,11 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-equal-assoc-types.rs:6:5 + | +LL | ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `<F as Foo>::Bar` does not have a fixed size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. From c7e83badf2796047650a58bde9ec3bf436d5ada8 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Fri, 28 Dec 2018 19:28:57 +0000 Subject: [PATCH 041/124] Fix warning when compiling rustc --- src/libstd/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index aa4278a879981..6ded43dfed1f4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -248,7 +248,6 @@ #![feature(const_cstr_unchecked)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] -#![cfg_attr(stage0, feature(duration_as_u128))] #![feature(exact_size_is_empty)] #![feature(external_doc)] #![feature(fixed_size_array)] From 07f6432f0ea16f6e21472039707e1ae47d491870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Fri, 28 Dec 2018 21:50:33 +0100 Subject: [PATCH 042/124] remove remaining copyright headers --- src/doc/rust.css | 12 ------------ src/libstd/sys/sgx/ext/arch.rs | 10 ---------- src/libstd/sys/sgx/ext/io.rs | 10 ---------- src/libstd/sys/sgx/ext/mod.rs | 10 ---------- src/test/rustdoc/issue-56822.rs | 10 ---------- .../rustfix/closure-immutable-outer-variable.fixed | 10 ---------- src/test/rustfix/empty-no-fixes.fixed | 10 ---------- src/test/rustfix/empty-no-fixes.rs.fixed | 10 ---------- src/test/rustfix/issue-45562.fixed | 10 ---------- ...d-extern-crate-rename-suggestion-formatting.fixed | 10 ---------- ...ue-46756-consider-borrowing-cast-or-binexpr.fixed | 10 ---------- src/test/rustfix/main-no-fixes.fixed | 10 ---------- src/test/rustfix/main-no-fixes.rs.fixed | 10 ---------- src/test/rustfix/missing-comma-in-match.fixed | 10 ---------- src/test/rustfix/str-as-char.fixed | 10 ---------- src/test/rustfix/tuple-float-index.fixed | 10 ---------- src/test/ui/attr-bad-crate-attr.rc | 10 ---------- .../closure-immutable-outer-variable.rs.fixed | 10 ---------- .../ui/kindck/kindck-send-unsafe.rs~rust-lang_master | 10 ---------- src/test/ui/lint/lint-group-nonstandard-style.rs | 4 ---- src/test/ui/lint/not_found.rs | 4 ---- 21 files changed, 200 deletions(-) diff --git a/src/doc/rust.css b/src/doc/rust.css index 5f216169efe2c..631f64a11dbae 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -1,15 +1,3 @@ -/** - * Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT - * file at the top-level directory of this distribution and at - * http://rust-lang.org/COPYRIGHT. - * With elements taken from Bootstrap v3.0.2 (MIT licensed). - * - * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or - * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license - * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ @font-face { font-family: 'Fira Sans'; font-style: normal; diff --git a/src/libstd/sys/sgx/ext/arch.rs b/src/libstd/sys/sgx/ext/arch.rs index 377210f5d699c..ba6f9e622ad35 100644 --- a/src/libstd/sys/sgx/ext/arch.rs +++ b/src/libstd/sys/sgx/ext/arch.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! SGX-specific access to architectural features. //! //! The functionality in this module is further documented in the Intel diff --git a/src/libstd/sys/sgx/ext/io.rs b/src/libstd/sys/sgx/ext/io.rs index 55cc4c9ba1ffb..1eb269783c5ab 100644 --- a/src/libstd/sys/sgx/ext/io.rs +++ b/src/libstd/sys/sgx/ext/io.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! SGX-specific extensions to general I/O primitives //! //! SGX file descriptors behave differently from Unix file descriptors. See the diff --git a/src/libstd/sys/sgx/ext/mod.rs b/src/libstd/sys/sgx/ext/mod.rs index 8e505a23c422d..5489f6f56946e 100644 --- a/src/libstd/sys/sgx/ext/mod.rs +++ b/src/libstd/sys/sgx/ext/mod.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![unstable(feature = "sgx_platform", issue = "56975")] pub mod arch; diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index 41aba1a007ad8..2d6cb1368d120 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - struct Wrapper<T>(T); trait MyTrait { diff --git a/src/test/rustfix/closure-immutable-outer-variable.fixed b/src/test/rustfix/closure-immutable-outer-variable.fixed index bddc2eab16dd8..05bbc13d714fa 100644 --- a/src/test/rustfix/closure-immutable-outer-variable.fixed +++ b/src/test/rustfix/closure-immutable-outer-variable.fixed @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Point at the captured immutable outer variable fn foo(mut f: Box<FnMut()>) { diff --git a/src/test/rustfix/empty-no-fixes.fixed b/src/test/rustfix/empty-no-fixes.fixed index 39e19566d7652..3724a00ce7ce0 100644 --- a/src/test/rustfix/empty-no-fixes.fixed +++ b/src/test/rustfix/empty-no-fixes.fixed @@ -1,11 +1 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // compile-flags:--crate-type lib diff --git a/src/test/rustfix/empty-no-fixes.rs.fixed b/src/test/rustfix/empty-no-fixes.rs.fixed index ee58e77825343..e30d3ae0965ae 100644 --- a/src/test/rustfix/empty-no-fixes.rs.fixed +++ b/src/test/rustfix/empty-no-fixes.rs.fixed @@ -1,12 +1,2 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // compile-flags:--crate-type lib fn foo() {} diff --git a/src/test/rustfix/issue-45562.fixed b/src/test/rustfix/issue-45562.fixed index d7a27a11fc07a..955b2cbf899ba 100644 --- a/src/test/rustfix/issue-45562.fixed +++ b/src/test/rustfix/issue-45562.fixed @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #[no_mangle] pub static RAH: usize = 5; fn main() {} diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed index d931f90cd0431..b4ae4dc1ab2f8 100644 --- a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed +++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -1,12 +1,2 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - extern crate std as other_std; fn main() {} diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed index aaa04ef40042d..bedc8e15ace6e 100644 --- a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed +++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![allow(unused)] fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { diff --git a/src/test/rustfix/main-no-fixes.fixed b/src/test/rustfix/main-no-fixes.fixed index 3f07b46791d22..f328e4d9d04c3 100644 --- a/src/test/rustfix/main-no-fixes.fixed +++ b/src/test/rustfix/main-no-fixes.fixed @@ -1,11 +1 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() {} diff --git a/src/test/rustfix/main-no-fixes.rs.fixed b/src/test/rustfix/main-no-fixes.rs.fixed index 3f07b46791d22..f328e4d9d04c3 100644 --- a/src/test/rustfix/main-no-fixes.rs.fixed +++ b/src/test/rustfix/main-no-fixes.rs.fixed @@ -1,11 +1 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() {} diff --git a/src/test/rustfix/missing-comma-in-match.fixed b/src/test/rustfix/missing-comma-in-match.fixed index 621a4127bc293..d4696ab9547a6 100644 --- a/src/test/rustfix/missing-comma-in-match.fixed +++ b/src/test/rustfix/missing-comma-in-match.fixed @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { match &Some(3) { &None => 1, diff --git a/src/test/rustfix/str-as-char.fixed b/src/test/rustfix/str-as-char.fixed index 0ace6d96613d7..900fee94653c1 100644 --- a/src/test/rustfix/str-as-char.fixed +++ b/src/test/rustfix/str-as-char.fixed @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn main() { println!("●●"); } diff --git a/src/test/rustfix/tuple-float-index.fixed b/src/test/rustfix/tuple-float-index.fixed index 9cb7537b42807..abb07962e894a 100644 --- a/src/test/rustfix/tuple-float-index.fixed +++ b/src/test/rustfix/tuple-float-index.fixed @@ -1,13 +1,3 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // compile-flags: -Z parse-only fn main () { diff --git a/src/test/ui/attr-bad-crate-attr.rc b/src/test/ui/attr-bad-crate-attr.rc index 4ab07f4fa9918..89ba26dfd6f4b 100644 --- a/src/test/ui/attr-bad-crate-attr.rc +++ b/src/test/ui/attr-bad-crate-attr.rc @@ -1,13 +1,3 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // error-pattern: expected item #![attr = "val"] diff --git a/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed index 80a5a45a30580..5c6358beb2487 100644 --- a/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed +++ b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Point at the captured immutable outer variable fn foo(mut f: Box<FnMut()>) { diff --git a/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master index a9bbfcfa26263..3f0444ec9c807 100644 --- a/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master +++ b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master @@ -1,13 +1,3 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - fn assert_send<T:Send>() { } // unsafe ptrs are ok unless they point at unsendable things diff --git a/src/test/ui/lint/lint-group-nonstandard-style.rs b/src/test/ui/lint/lint-group-nonstandard-style.rs index 1e99764df15be..0386daaa59b07 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.rs +++ b/src/test/ui/lint/lint-group-nonstandard-style.rs @@ -1,7 +1,3 @@ -// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT -// http://rust-lang.org/COPYRIGHT. -// - #![deny(nonstandard_style)] #![allow(dead_code)] diff --git a/src/test/ui/lint/not_found.rs b/src/test/ui/lint/not_found.rs index a3e301d6bd039..0b5a4eb785195 100644 --- a/src/test/ui/lint/not_found.rs +++ b/src/test/ui/lint/not_found.rs @@ -1,7 +1,3 @@ -// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT -// http://rust-lang.org/COPYRIGHT. -// - // compile-pass // this tests the `unknown_lint` lint, especially the suggestions From 2c3d19489f4434c467d7fa299690601309887bc8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sat, 29 Dec 2018 00:15:19 +0300 Subject: [PATCH 043/124] resolve: Fix another ICE in import validation --- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_resolve/resolve_imports.rs | 2 +- .../uniform-paths/auxiliary/issue-56596-2.rs | 1 + src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs | 11 +++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0db6dbafb6cc6..6c7d0efbc0297 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1014,11 +1014,11 @@ enum ModuleOrUniformRoot<'a> { CurrentScope, } -impl<'a> PartialEq for ModuleOrUniformRoot<'a> { - fn eq(&self, other: &Self) -> bool { - match (*self, *other) { +impl ModuleOrUniformRoot<'_> { + fn same_def(lhs: Self, rhs: Self) -> bool { + match (lhs, rhs) { (ModuleOrUniformRoot::Module(lhs), - ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), + ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(), (ModuleOrUniformRoot::CrateRootAndExternPrelude, ModuleOrUniformRoot::CrateRootAndExternPrelude) | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 5830aa3713d83..ba4b18abdfc98 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -848,7 +848,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. if let Some(initial_module) = directive.imported_module.get() { - if module != initial_module && no_ambiguity { + if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { span_bug!(directive.span, "inconsistent resolution for an import"); } } else { diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs new file mode 100644 index 0000000000000..db723075f93c0 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs @@ -0,0 +1 @@ +pub extern crate core; diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs new file mode 100644 index 0000000000000..9ec3a64113116 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs @@ -0,0 +1,11 @@ +// compile-pass +// edition:2018 +// compile-flags: --extern issue_56596_2 +// aux-build:issue-56596-2.rs + +mod m { + use core::any; + pub use issue_56596_2::*; +} + +fn main() {} From 42730aa70d2b9315f065b40989e405d5ea26e701 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sat, 29 Dec 2018 02:48:38 +0300 Subject: [PATCH 044/124] resolve: Never override real bindings with `Def::Err`s from error recovery --- src/librustc_resolve/resolve_imports.rs | 4 ++++ src/test/ui/imports/duplicate.rs | 2 +- src/test/ui/imports/duplicate.stderr | 21 +-------------------- src/test/ui/imports/issue-56125.stderr | 10 +++++----- src/test/ui/imports/issue-57015.rs | 13 +++++++++++++ src/test/ui/imports/issue-57015.stderr | 9 +++++++++ 6 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 src/test/ui/imports/issue-57015.rs create mode 100644 src/test/ui/imports/issue-57015.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ba4b18abdfc98..ab440eda538a9 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -472,6 +472,10 @@ impl<'a> Resolver<'a> { self.set_binding_parent_module(binding, module); self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { + if binding.def() == Def::Err { + // Do not override real bindings with `Def::Err`s from error recovery. + return Ok(()); + } match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { if binding.def() != old_binding.def() { diff --git a/src/test/ui/imports/duplicate.rs b/src/test/ui/imports/duplicate.rs index 95bb69043e9bf..d62bbf765b787 100644 --- a/src/test/ui/imports/duplicate.rs +++ b/src/test/ui/imports/duplicate.rs @@ -33,7 +33,7 @@ mod g { fn main() { e::foo(); f::foo(); //~ ERROR `foo` is ambiguous - g::foo(); //~ ERROR `foo` is ambiguous + g::foo(); } mod ambiguous_module_errors { diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 3df2c5930e86e..acd66826fdfb7 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -50,25 +50,6 @@ LL | pub use b::*; | ^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) - --> $DIR/duplicate.rs:36:8 - | -LL | g::foo(); //~ ERROR `foo` is ambiguous - | ^^^ ambiguous name - | -note: `foo` could refer to the function imported here - --> $DIR/duplicate.rs:29:13 - | -LL | pub use a::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate -note: `foo` could also refer to the unresolved item imported here - --> $DIR/duplicate.rs:30:13 - | -LL | pub use f::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate - error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) --> $DIR/duplicate.rs:49:9 | @@ -88,7 +69,7 @@ LL | use self::m2::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors occurred: E0252, E0659. For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr index 559979e5d51c3..210f6a4399635 100644 --- a/src/test/ui/imports/issue-56125.stderr +++ b/src/test/ui/imports/issue-56125.stderr @@ -42,12 +42,12 @@ LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous | = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously -note: `issue_56125` could also refer to the unresolved item imported here - --> $DIR/issue-56125.rs:19:9 +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:20:9 | -LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` - | ^^^^^^^^^^^^^^^^^^ - = help: use `self::issue_56125` to refer to this unresolved item unambiguously +LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous + | ^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously error: aborting due to 4 previous errors diff --git a/src/test/ui/imports/issue-57015.rs b/src/test/ui/imports/issue-57015.rs new file mode 100644 index 0000000000000..27688fd34f62f --- /dev/null +++ b/src/test/ui/imports/issue-57015.rs @@ -0,0 +1,13 @@ +mod glob_ok { + pub mod something { + pub mod something_else {} + } +} + +mod single_err {} + +use glob_ok::*; // glob_ok::something +use single_err::something; //~ ERROR unresolved import `single_err::something` +use something::something_else; + +fn main() {} diff --git a/src/test/ui/imports/issue-57015.stderr b/src/test/ui/imports/issue-57015.stderr new file mode 100644 index 0000000000000..b0fcf5bec6a77 --- /dev/null +++ b/src/test/ui/imports/issue-57015.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `single_err::something` + --> $DIR/issue-57015.rs:10:5 + | +LL | use single_err::something; //~ ERROR unresolved import `single_err::something` + | ^^^^^^^^^^^^^^^^^^^^^ no `something` in `single_err` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. From 7848878c6e0deb4467cd145944e74121ba054038 Mon Sep 17 00:00:00 2001 From: Eric Huss <eric@huss.org> Date: Mon, 17 Dec 2018 10:23:04 -0800 Subject: [PATCH 045/124] Update cargo, rls, miri --- Cargo.lock | 117 +++++++++++----------- Cargo.toml | 1 - src/bootstrap/test.rs | 7 -- src/bootstrap/tool.rs | 2 +- src/tools/cargo | 2 +- src/tools/miri | 2 +- src/tools/rls | 2 +- src/tools/rustc-workspace-hack/Cargo.toml | 1 + src/tools/tidy/src/deps.rs | 5 + 9 files changed, 68 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f19238140b806..328c145edc4dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,7 +140,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -156,7 +156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -208,8 +208,8 @@ dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -219,7 +219,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -228,11 +228,10 @@ dependencies = [ "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -252,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -328,7 +327,7 @@ dependencies = [ "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -360,7 +359,7 @@ dependencies = [ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,8 +429,8 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -450,7 +449,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -484,7 +483,7 @@ version = "0.22.0" dependencies = [ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -683,7 +682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -894,12 +893,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "git2" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -908,11 +907,11 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -949,7 +948,7 @@ dependencies = [ "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1097,12 +1096,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "8.0.1" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1124,7 +1123,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1156,7 +1155,7 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1214,14 +1213,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.6" @@ -1271,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1303,7 +1294,7 @@ dependencies = [ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1390,8 +1381,10 @@ dependencies = [ "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-workspace-hack 1.0.0", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1965,10 +1958,12 @@ dependencies = [ "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1988,9 +1983,10 @@ dependencies = [ "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", "rustfmt-nightly 1.0.1", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2023,7 +2019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2038,7 +2034,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2263,6 +2259,7 @@ version = "1.0.0" dependencies = [ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2709,12 +2706,12 @@ dependencies = [ [[package]] name = "rustfix" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2740,7 +2737,7 @@ dependencies = [ "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2797,7 +2794,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2807,8 +2804,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" @@ -2825,7 +2825,7 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2835,7 +2835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2917,7 +2917,7 @@ dependencies = [ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3134,7 +3134,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3154,7 +3154,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3252,7 +3252,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3461,8 +3461,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" -"checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" -"checksum git2-curl 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0173e317f8ba21f3fff0f71549fead5e42e67961dbd402bf69f42775f3cc78b4" +"checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" +"checksum git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d58551e903ed7e2d6fe3a2f3c7efa3a784ec29b19d0fbb035aaf0497c183fbdd" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd" @@ -3481,19 +3481,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" -"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" +"checksum jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e9cbeda300803d381390fb65e8158437728c39e6987ed23bee82728b73511a7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68de833188ada4e175d04a028f03f244f6370eedbcc75a05604d47d925933f69" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" -"checksum libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4916b5addc78ec36cc309acfcdf0b9f9d97ab7b84083118b248709c5b7029356" +"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614" @@ -3593,7 +3592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b" +"checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56" "checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" @@ -3602,7 +3601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" +"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" "checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" diff --git a/Cargo.toml b/Cargo.toml index 667c55791bd17..c693985a2ad83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ members = [ "src/tools/rustdoc-themes", ] exclude = [ - "src/tools/rls/test_data", "build", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b6f3f97e627fd..2edc78ebaa94f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -283,13 +283,6 @@ impl Step for Rls { SourceType::Submodule, &[]); - // Copy `src/tools/rls/test_data` to a writable drive. - let test_workspace_path = builder.out.join("rls-test-data"); - let test_data_path = test_workspace_path.join("test_data"); - builder.create_dir(&test_data_path); - builder.cp_r(&builder.src.join("src/tools/rls/test_data"), &test_data_path); - cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path); - builder.add_rustc_lib_path(compiler, &mut cargo); cargo.arg("--") .args(builder.config.cmd.test_args()); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 1a5a874049900..7782351a552d4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -140,7 +140,7 @@ impl Step for ToolBuild { }); if is_expected && !duplicates.is_empty() { - println!("duplicate artfacts found when compiling a tool, this \ + println!("duplicate artifacts found when compiling a tool, this \ typically means that something was recompiled because \ a transitive dependency has different features activated \ than in a previous build:\n"); diff --git a/src/tools/cargo b/src/tools/cargo index 2cf1f5dda2f7e..0d1f1bbeabd5b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 2cf1f5dda2f7ed84e94c4d32f643e0f1f15352f0 +Subproject commit 0d1f1bbeabd5b43a7f3ecfa16540af8e76d5efb4 diff --git a/src/tools/miri b/src/tools/miri index bccadeb4f7cbe..2e2a33aab8972 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit bccadeb4f7cbeeb14097a365653148afe8bbd159 +Subproject commit 2e2a33aab897273a36498d526530f648d6113dc8 diff --git a/src/tools/rls b/src/tools/rls index bd5b899afb05e..6f5e4bba7b158 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit bd5b899afb05e14d33e210ede3da241ca1ca088f +Subproject commit 6f5e4bba7b1586fca6e0ea7724cadb5683b2f308 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 5acfee28fad67..ca440167f9f07 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -53,6 +53,7 @@ features = [ curl-sys = { version = "0.4.13", optional = true } parking_lot = { version = "0.6", features = ['nightly'] } rand = { version = "0.5.5", features = ["i128_support"] } +serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value"] } smallvec = { version = "0.6", features = ['union'] } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ff7a040ca09a5..7f0f0c6f79fcc 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -106,7 +106,9 @@ const WHITELIST: &[Crate] = &[ Crate("parking_lot_core"), Crate("pkg-config"), Crate("polonius-engine"), + Crate("proc-macro2"), Crate("quick-error"), + Crate("quote"), Crate("rand"), Crate("rand_chacha"), Crate("rand_core"), @@ -129,8 +131,10 @@ const WHITELIST: &[Crate] = &[ Crate("semver"), Crate("semver-parser"), Crate("serde"), + Crate("serde_derive"), Crate("smallvec"), Crate("stable_deref_trait"), + Crate("syn"), Crate("tempfile"), Crate("termcolor"), Crate("terminon"), @@ -138,6 +142,7 @@ const WHITELIST: &[Crate] = &[ Crate("thread_local"), Crate("ucd-util"), Crate("unicode-width"), + Crate("unicode-xid"), Crate("unreachable"), Crate("utf8-ranges"), Crate("vcpkg"), From 2b7ff35556c4eb158b6cf3ca61c4ef288d5db6d2 Mon Sep 17 00:00:00 2001 From: csmoe <csmoe@msn.com> Date: Thu, 27 Dec 2018 19:08:51 +0800 Subject: [PATCH 046/124] add non-copy note to stderr --- .../borrowck-describe-lvalue.ast.nll.stderr | 2 +- .../borrowck-describe-lvalue.mir.stderr | 2 +- .../borrowck-field-sensitivity.nll.stderr | 4 ++++ ...orrowck-move-out-from-array.ast.nll.stderr | 19 ------------------- .../borrowck-move-out-from-array.mir.stderr | 4 ++++ ...rowck-vec-pattern-move-tail.ast.nll.stderr | 6 +++--- .../borrowck-vec-pattern-move-tail.cmp.stderr | 6 +++--- .../borrowck-vec-pattern-nesting.nll.stderr | 12 ++++++------ .../two-phase-nonrecv-autoref.ast.nll.stderr | 4 ++++ .../two-phase-nonrecv-autoref.nll.stderr | 4 ++++ ...e-27282-move-match-input-into-guard.stderr | 2 ++ src/test/ui/issues/issue-42344.nll.stderr | 2 +- src/test/ui/issues/issue-46604.ast.nll.stderr | 2 +- src/test/ui/issues/issue-46604.mir.stderr | 2 +- .../liveness-use-after-move.nll.stderr | 2 ++ src/test/ui/nll/drop-no-may-dangle.stderr | 16 ++++++++-------- .../borrow-after-move.nll.stderr | 6 ++++++ .../ui/unsized-locals/double-move.nll.stderr | 8 ++++++++ .../ui/use/use-after-move-self.nll.stderr | 2 ++ src/test/ui/use/use-after-move-self.rs | 2 +- 20 files changed, 62 insertions(+), 45 deletions(-) delete mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr index 410b94b34bcac..24467faa90ca9 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:261:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr index ab208ee20c5ef..279548f870fd0 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:261:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr index 93e2dd49f7bfa..25a9a11204430 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr @@ -5,6 +5,8 @@ LL | drop(x.b); | --- value moved here LL | drop(*x.b); //~ ERROR use of moved value: `*x.b` | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:14:10 @@ -13,6 +15,8 @@ LL | let y = A { a: 3, .. x }; | ---------------- value moved here LL | drop(*x.b); //~ ERROR use of moved value: `*x.b` | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:20:13 diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr deleted file mode 100644 index 2e5477c573bbe..0000000000000 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:10:14 - | -LL | let [_, _x] = a; - | -- value moved here -LL | let [.., _y] = a; //[ast]~ ERROR [E0382] - | ^^ value used here after move - -error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:17:10 - | -LL | let [_x, _] = a; - | -- value moved here -LL | let [_y..] = a; //[ast]~ ERROR [E0382] - | ^^ value used here after move - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr index 2e5477c573bbe..f866ff9e9bae1 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr @@ -5,6 +5,8 @@ LL | let [_, _x] = a; | -- value moved here LL | let [.., _y] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array.rs:17:10 @@ -13,6 +15,8 @@ LL | let [_x, _] = a; | -- value moved here LL | let [_y..] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr index 9577a41bb182e..6dc2778892d2e 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr @@ -1,11 +1,11 @@ -error[E0506]: cannot assign to `a[..]` because it is borrowed +error[E0506]: cannot assign to `a[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr index 0e4a3cd6c1b50..6eb9eac760f00 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr @@ -7,14 +7,14 @@ LL | [1, 2, ref tail..] => tail, LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed | ^^^^^^^^ assignment to borrowed `a[..]` occurs here -error[E0506]: cannot assign to `a[..]` because it is borrowed (Mir) +error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir) --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr index 6a3c051e34989..018a3173af1b0 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `vec[..]` because it is borrowed +error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:10:13 | LL | [box ref _a, _, _] => { - | ------ borrow of `vec[..]` occurs here + | ------ borrow of `vec[_]` occurs here LL | //~^ borrow of `vec[..]` occurs here LL | vec[0] = box 4; //~ ERROR cannot assign - | ^^^^^^ assignment to borrowed `vec[..]` occurs here + | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | //~^ assignment to borrowed `vec[..]` occurs here LL | _a.use_ref(); | -- borrow later used here -error[E0506]: cannot assign to `vec[..]` because it is borrowed +error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:23:13 | LL | &mut [ref _b..] => { - | ------ borrow of `vec[..]` occurs here + | ------ borrow of `vec[_]` occurs here LL | //~^ borrow of `vec[..]` occurs here LL | vec[0] = box 4; //~ ERROR cannot assign - | ^^^^^^ assignment to borrowed `vec[..]` occurs here + | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | //~^ assignment to borrowed `vec[..]` occurs here LL | _b.use_ref(); | -- borrow later used here diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr index 1fdde5e15f364..0e99e158eda02 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:129:27 diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index 1fdde5e15f364..0e99e158eda02 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:129:27 diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index be393c5e4f509..8ea2bdb693d31 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -8,6 +8,8 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); LL | false } => { }, LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move + | + = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42344.nll.stderr b/src/test/ui/issues/issue-42344.nll.stderr index 046a45241cdd7..9770d26fb12d8 100644 --- a/src/test/ui/issues/issue-42344.nll.stderr +++ b/src/test/ui/issues/issue-42344.nll.stderr @@ -1,4 +1,4 @@ -error[E0596]: cannot borrow `*TAB[..]` as mutable, as `TAB` is an immutable static item +error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable static item --> $DIR/issue-42344.rs:4:5 | LL | TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389] diff --git a/src/test/ui/issues/issue-46604.ast.nll.stderr b/src/test/ui/issues/issue-46604.ast.nll.stderr index ed23a69edb987..4f73a0f9d541d 100644 --- a/src/test/ui/issues/issue-46604.ast.nll.stderr +++ b/src/test/ui/issues/issue-46604.ast.nll.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:10:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr index ed23a69edb987..4f73a0f9d541d 100644 --- a/src/test/ui/issues/issue-46604.mir.stderr +++ b/src/test/ui/issues/issue-46604.mir.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:10:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/liveness/liveness-use-after-move.nll.stderr b/src/test/ui/liveness/liveness-use-after-move.nll.stderr index 01534d0c0f667..45fd43687f39b 100644 --- a/src/test/ui/liveness/liveness-use-after-move.nll.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.nll.stderr @@ -5,6 +5,8 @@ LL | let y = x; | - value moved here LL | println!("{}", *x); //~ ERROR use of moved value: `*x` | ^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index 28dc686e95cf1..efa825be295f2 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:20:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here ... LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:23:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` diff --git a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr index a3cfcc8921766..18cba2047356a 100644 --- a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr +++ b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr @@ -6,6 +6,8 @@ LL | let y = *x; LL | drop_unsized(y); LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:22:24 @@ -26,6 +28,8 @@ LL | let y = *x; LL | y.foo(); LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:32:24 @@ -45,6 +49,8 @@ LL | x.foo(); | - value moved here LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error: aborting due to 5 previous errors diff --git a/src/test/ui/unsized-locals/double-move.nll.stderr b/src/test/ui/unsized-locals/double-move.nll.stderr index 0555a8944bf94..bbe6da70fb112 100644 --- a/src/test/ui/unsized-locals/double-move.nll.stderr +++ b/src/test/ui/unsized-locals/double-move.nll.stderr @@ -15,6 +15,8 @@ LL | let _y = *x; | -- value moved here LL | drop_unsized(x); //~ERROR use of moved value | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:32:18 @@ -23,6 +25,8 @@ LL | drop_unsized(x); | - value moved here LL | let _y = *x; //~ERROR use of moved value | ^^ value used here after move + | + = note: move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `y` --> $DIR/double-move.rs:39:9 @@ -41,6 +45,8 @@ LL | let _y = *x; | -- value moved here LL | x.foo(); //~ERROR use of moved value | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 @@ -49,6 +55,8 @@ LL | x.foo(); | - value moved here LL | let _y = *x; //~ERROR use of moved value | ^^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/use/use-after-move-self.nll.stderr b/src/test/ui/use/use-after-move-self.nll.stderr index 28ee8224af39a..3e11e94e993f5 100644 --- a/src/test/ui/use/use-after-move-self.nll.stderr +++ b/src/test/ui/use/use-after-move-self.nll.stderr @@ -5,6 +5,8 @@ LL | self.bar(); | ---- value moved here LL | return *self.x; //~ ERROR use of moved value: `*self.x` | ^^^^^^^ value used here after move + | + = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs index a6f6c45573d0a..1337d61a6d8e8 100644 --- a/src/test/ui/use/use-after-move-self.rs +++ b/src/test/ui/use/use-after-move-self.rs @@ -7,7 +7,7 @@ struct S { impl S { pub fn foo(self) -> isize { self.bar(); - return *self.x; //~ ERROR use of moved value: `self` + return *self.x; //~ ERROR use of moved value: `*self.x` } pub fn bar(self) {} From 9b9fd0382ddb5ec22b824cd2c4d8b36c44788592 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro <alexreg@me.com> Date: Sat, 29 Dec 2018 05:45:45 +0000 Subject: [PATCH 047/124] Fixed stderr files for ui tests. --- src/test/ui/error-codes/E0110.rs | 3 +-- src/test/ui/error-codes/E0110.stderr | 8 -------- .../rfc1598-generic-associated-types/collections.stderr | 4 ++-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/test/ui/error-codes/E0110.rs b/src/test/ui/error-codes/E0110.rs index 2de5da16ad76a..764b62b8dfecf 100644 --- a/src/test/ui/error-codes/E0110.rs +++ b/src/test/ui/error-codes/E0110.rs @@ -1,4 +1,3 @@ type X = u32<'static>; //~ ERROR E0110 -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index be9b4229aeb60..a644ac92cefbf 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -1,13 +1,5 @@ -<<<<<<< HEAD error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/E0110.rs:1:14 -||||||| merged common ancestors -error[E0110]: lifetime parameters are not allowed on this type - --> $DIR/E0110.rs:11:14 -======= -error[E0110]: lifetime arguments are not allowed on this entity - --> $DIR/E0110.rs:11:14 ->>>>>>> Added regression test for using generic parameters on modules. | LL | type X = u32<'static>; //~ ERROR E0110 | ^^^^^^^ lifetime argument not allowed diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr index b3fb81b418e8c..eeed04bd89213 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/collections.stderr @@ -22,13 +22,13 @@ error[E0109]: type arguments are not allowed on this entity LL | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; | ^ type argument not allowed -error[E0109]: type arguments are not allowed on this entity +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/collections.rs:24:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; | ^^^^^ lifetime argument not allowed -error[E0109]: type arguments are not allowed on this entity +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/collections.rs:50:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { From c1bea3bc1bde467145b4546b77951452431c4a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sat, 29 Dec 2018 08:52:25 +0100 Subject: [PATCH 048/124] update tests line numbers --- .../lint/lint-group-nonstandard-style.stderr | 20 +++++++++---------- src/test/ui/lint/not_found.stderr | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index a6f751d15841d..d85ca7811d01e 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -1,63 +1,63 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` - --> $DIR/lint-group-nonstandard-style.rs:26:9 + --> $DIR/lint-group-nonstandard-style.rs:22:9 | LL | struct snake_case; //~ WARN should have a camel | ^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:22:17 + --> $DIR/lint-group-nonstandard-style.rs:18:17 | LL | #![warn(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)] error: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:8:1 + --> $DIR/lint-group-nonstandard-style.rs:4:1 | LL | fn CamelCase() {} //~ ERROR should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:5:9 + --> $DIR/lint-group-nonstandard-style.rs:1:9 | LL | #![deny(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)] error: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:16:9 + --> $DIR/lint-group-nonstandard-style.rs:12:9 | LL | fn CamelCase() {} //~ ERROR should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:14:14 + --> $DIR/lint-group-nonstandard-style.rs:10:14 | LL | #[forbid(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)] error: static variable `bad` should have an upper case name such as `BAD` - --> $DIR/lint-group-nonstandard-style.rs:18:9 + --> $DIR/lint-group-nonstandard-style.rs:14:9 | LL | static bad: isize = 1; //~ ERROR should have an upper | ^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:14:14 + --> $DIR/lint-group-nonstandard-style.rs:10:14 | LL | #[forbid(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)] warning: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:24:9 + --> $DIR/lint-group-nonstandard-style.rs:20:9 | LL | fn CamelCase() {} //~ WARN should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:22:17 + --> $DIR/lint-group-nonstandard-style.rs:18:17 | LL | #![warn(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 5ae7fb352d668..266cf10af8285 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -1,5 +1,5 @@ warning: unknown lint: `FOO_BAR` - --> $DIR/not_found.rs:10:9 + --> $DIR/not_found.rs:6:9 | LL | #[allow(FOO_BAR)] | ^^^^^^^ @@ -7,13 +7,13 @@ LL | #[allow(FOO_BAR)] = note: #[warn(unknown_lints)] on by default warning: unknown lint: `DEAD_CODE` - --> $DIR/not_found.rs:12:8 + --> $DIR/not_found.rs:8:8 | LL | #[warn(DEAD_CODE)] | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` - --> $DIR/not_found.rs:14:8 + --> $DIR/not_found.rs:10:8 | LL | #[deny(Warnings)] | ^^^^^^^^ help: did you mean: `warnings` From 643e4e63e30f72163a1f9f800d2c5eb71d7909da Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sat, 29 Dec 2018 18:15:29 +0300 Subject: [PATCH 049/124] resolve: Simplify treatment of ambiguity errors --- src/librustc_resolve/build_reduced_graph.rs | 3 + src/librustc_resolve/lib.rs | 63 ++++++++----------- src/librustc_resolve/macros.rs | 7 ++- src/librustc_resolve/resolve_imports.rs | 29 +++++---- .../ui/imports/auxiliary/glob-conflict.rs | 4 ++ src/test/ui/imports/duplicate.rs | 2 +- .../ui/imports/glob-conflict-cross-crate.rs | 1 + .../imports/glob-conflict-cross-crate.stderr | 8 ++- 8 files changed, 63 insertions(+), 54 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 21fb29974c880..a452bbf0c9d54 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -42,6 +42,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Module(self.0), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, @@ -53,6 +54,7 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(self.0, false), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, @@ -66,6 +68,7 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(self.0, true), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6c7d0efbc0297..d16e097e3a52e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1191,6 +1191,7 @@ impl<'a> fmt::Debug for ModuleData<'a> { #[derive(Clone, Debug)] pub struct NameBinding<'a> { kind: NameBindingKind<'a>, + ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, expansion: Mark, span: Span, vis: ty::Visibility, @@ -1215,11 +1216,6 @@ enum NameBindingKind<'a> { directive: &'a ImportDirective<'a>, used: Cell<bool>, }, - Ambiguity { - kind: AmbiguityKind, - b1: &'a NameBinding<'a>, - b2: &'a NameBinding<'a>, - } } struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>); @@ -1309,15 +1305,13 @@ impl<'a> NameBinding<'a> { NameBindingKind::Def(def, _) => def, NameBindingKind::Module(module) => module.def().unwrap(), NameBindingKind::Import { binding, .. } => binding.def(), - NameBindingKind::Ambiguity { .. } => Def::Err, } } - fn def_ignoring_ambiguity(&self) -> Def { - match self.kind { - NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(), - NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(), - _ => self.def(), + fn is_ambiguity(&self) -> bool { + self.ambiguity.is_some() || match self.kind { + NameBindingKind::Import { binding, .. } => binding.is_ambiguity(), + _ => false, } } @@ -1362,7 +1356,6 @@ impl<'a> NameBinding<'a> { fn is_glob_import(&self) -> bool { match self.kind { NameBindingKind::Import { directive, .. } => directive.is_glob(), - NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(), _ => false, } } @@ -1382,7 +1375,7 @@ impl<'a> NameBinding<'a> { } fn macro_kind(&self) -> Option<MacroKind> { - match self.def_ignoring_ambiguity() { + match self.def() { Def::Macro(_, kind) => Some(kind), Def::NonMacroAttr(..) => Some(MacroKind::Attr), _ => None, @@ -1893,6 +1886,7 @@ impl<'a> Resolver<'a> { arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Err, false), + ambiguity: None, expansion: Mark::root(), span: DUMMY_SP, vis: ty::Visibility::Public, @@ -1963,33 +1957,30 @@ impl<'a> Resolver<'a> { fn record_use(&mut self, ident: Ident, ns: Namespace, used_binding: &'a NameBinding<'a>, is_lexical_scope: bool) { - match used_binding.kind { - NameBindingKind::Import { directive, binding, ref used } if !used.get() => { - // Avoid marking `extern crate` items that refer to a name from extern prelude, - // but not introduce it, as used if they are accessed from lexical scope. - if is_lexical_scope { - if let Some(entry) = self.extern_prelude.get(&ident.modern()) { - if let Some(crate_item) = entry.extern_crate_item { - if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { - return; - } + if let Some((b2, kind)) = used_binding.ambiguity { + self.ambiguity_errors.push(AmbiguityError { + kind, ident, b1: used_binding, b2, + misc1: AmbiguityErrorMisc::None, + misc2: AmbiguityErrorMisc::None, + }); + } + if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind { + // Avoid marking `extern crate` items that refer to a name from extern prelude, + // but not introduce it, as used if they are accessed from lexical scope. + if is_lexical_scope { + if let Some(entry) = self.extern_prelude.get(&ident.modern()) { + if let Some(crate_item) = entry.extern_crate_item { + if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { + return; } } } - used.set(true); - directive.used.set(true); - self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(directive.id, ident); - self.record_use(ident, ns, binding, false); - } - NameBindingKind::Ambiguity { kind, b1, b2 } => { - self.ambiguity_errors.push(AmbiguityError { - kind, ident, b1, b2, - misc1: AmbiguityErrorMisc::None, - misc2: AmbiguityErrorMisc::None, - }); } - _ => {} + used.set(true); + directive.used.set(true); + self.used_imports.insert((directive.id, ns)); + self.add_to_glob_map(directive.id, ident); + self.record_use(ident, ns, binding, false); } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 8454dbc3410c9..7585076bc75f6 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -175,6 +175,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_map.insert(def_id, ext); let binding = self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Macro(def_id, kind), false), + ambiguity: None, span: DUMMY_SP, vis: ty::Visibility::Public, expansion: Mark::root(), @@ -389,7 +390,7 @@ impl<'a> Resolver<'a> { .push((path[0].ident, kind, parent_scope.clone(), binding.ok())); } - binding.map(|binding| binding.def_ignoring_ambiguity()) + binding.map(|binding| binding.def()) } } @@ -950,9 +951,9 @@ impl<'a> Resolver<'a> { Ok(binding) => { let initial_def = initial_binding.map(|initial_binding| { self.record_use(ident, MacroNS, initial_binding, false); - initial_binding.def_ignoring_ambiguity() + initial_binding.def() }); - let def = binding.def_ignoring_ambiguity(); + let def = binding.def(); let seg = Segment::from_ident(ident); check_consistency(self, &[seg], ident.span, kind, initial_def, def); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ab440eda538a9..c84dbd2974624 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -445,6 +445,7 @@ impl<'a> Resolver<'a> { directive, used: Cell::new(false), }, + ambiguity: None, span: directive.span, vis, expansion: directive.parent_scope.expansion, @@ -498,8 +499,8 @@ impl<'a> Resolver<'a> { nonglob_binding, glob_binding)); } else { resolution.binding = Some(nonglob_binding); - resolution.shadowed_glob = Some(glob_binding); } + resolution.shadowed_glob = Some(glob_binding); } (false, false) => { if let (&NameBindingKind::Def(_, true), &NameBindingKind::Def(_, true)) = @@ -527,13 +528,15 @@ impl<'a> Resolver<'a> { }) } - fn ambiguity(&self, kind: AmbiguityKind, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>) - -> &'a NameBinding<'a> { + fn ambiguity(&self, kind: AmbiguityKind, + primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>) + -> &'a NameBinding<'a> { self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Ambiguity { kind, b1, b2 }, - vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis }, - span: b1.span, - expansion: Mark::root(), + kind: primary_binding.kind.clone(), + ambiguity: Some((secondary_binding, kind)), + vis: primary_binding.vis, + span: primary_binding.span, + expansion: primary_binding.expansion, }) } @@ -962,9 +965,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { directive.module_path.is_empty()); } } - initial_binding.def_ignoring_ambiguity() + initial_binding.def() }); - let def = binding.def_ignoring_ambiguity(); + let def = binding.def(); if let Ok(initial_def) = initial_def { if def != initial_def && this.ambiguity_errors.is_empty() { span_bug!(directive.span, "inconsistent resolution for an import"); @@ -1201,10 +1204,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => continue, }; - // Filter away "empty import canaries". - let is_non_canary_import = - binding.is_import() && binding.vis != ty::Visibility::Invisible; - if is_non_canary_import || binding.is_macro_def() { + // Filter away "empty import canaries" and ambiguous imports. + let is_good_import = binding.is_import() && !binding.is_ambiguity() && + binding.vis != ty::Visibility::Invisible; + if is_good_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { if let Some(def_id) = def.opt_def_id() { diff --git a/src/test/ui/imports/auxiliary/glob-conflict.rs b/src/test/ui/imports/auxiliary/glob-conflict.rs index ac12ed9c81c77..c83db64c6437c 100644 --- a/src/test/ui/imports/auxiliary/glob-conflict.rs +++ b/src/test/ui/imports/auxiliary/glob-conflict.rs @@ -7,3 +7,7 @@ mod m2 { pub use m1::*; pub use m2::*; + +pub mod glob { + pub use *; +} diff --git a/src/test/ui/imports/duplicate.rs b/src/test/ui/imports/duplicate.rs index d62bbf765b787..db6538969ec71 100644 --- a/src/test/ui/imports/duplicate.rs +++ b/src/test/ui/imports/duplicate.rs @@ -37,7 +37,7 @@ fn main() { } mod ambiguous_module_errors { - pub mod m1 { pub use super::m1 as foo; } + pub mod m1 { pub use super::m1 as foo; pub fn bar() {} } pub mod m2 { pub use super::m2 as foo; } use self::m1::*; diff --git a/src/test/ui/imports/glob-conflict-cross-crate.rs b/src/test/ui/imports/glob-conflict-cross-crate.rs index e02148b19f786..c8b18525d8059 100644 --- a/src/test/ui/imports/glob-conflict-cross-crate.rs +++ b/src/test/ui/imports/glob-conflict-cross-crate.rs @@ -4,4 +4,5 @@ extern crate glob_conflict; fn main() { glob_conflict::f(); //~ ERROR cannot find function `f` in module `glob_conflict` + glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` } diff --git a/src/test/ui/imports/glob-conflict-cross-crate.stderr b/src/test/ui/imports/glob-conflict-cross-crate.stderr index f64637fd6f625..f5a82ef1b3b01 100644 --- a/src/test/ui/imports/glob-conflict-cross-crate.stderr +++ b/src/test/ui/imports/glob-conflict-cross-crate.stderr @@ -4,6 +4,12 @@ error[E0425]: cannot find function `f` in module `glob_conflict` LL | glob_conflict::f(); //~ ERROR cannot find function `f` in module `glob_conflict` | ^ not found in `glob_conflict` -error: aborting due to previous error +error[E0425]: cannot find function `f` in module `glob_conflict::glob` + --> $DIR/glob-conflict-cross-crate.rs:7:26 + | +LL | glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` + | ^ not found in `glob_conflict::glob` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. From f5f5d4cd1b2e3f8da326c62c1cd7660b9777dbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Sat, 29 Dec 2018 10:54:32 -0800 Subject: [PATCH 050/124] Use `same_type` instead of duplicating logic --- src/librustc/infer/error_reporting/mod.rs | 31 +++++++++-------------- src/librustc/ty/util.rs | 28 ++++++++++---------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index c9fc896b1b2d4..e34bb9f4f7bd9 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1005,26 +1005,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { let mut show_suggestion = true; for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { - if let TyKind::Ref(_, exp_ty, _) = exp_ty.sty { - match (&exp_ty.sty, &found_ty.sty) { - (TyKind::Adt(exp_did, _), TyKind::Adt(found_did, _)) - if exp_did == found_did => {} - (TyKind::Bool, TyKind::Bool) | - (TyKind::Char, TyKind::Char) | - (TyKind::Str, TyKind::Str) | - (_, TyKind::Param(_)) | - (_, TyKind::Infer(_)) | - (TyKind::Param(_), _) | - (TyKind::Infer(_), _) => {} - (TyKind::Int(x), TyKind::Int(y)) if x == y => {} - (TyKind::Uint(x), TyKind::Uint(y)) if x == y => {} - (TyKind::Int(x), TyKind::Int(y)) if x == y => {} - (TyKind::Uint(x), TyKind::Uint(y)) if x == y => {} - (TyKind::Float(x), TyKind::Float(y)) if x == y => {} - _ => show_suggestion = false, + match exp_ty.sty { + TyKind::Ref(_, exp_ty, _) => { + match (&exp_ty.sty, &found_ty.sty) { + (_, TyKind::Param(_)) | + (_, TyKind::Infer(_)) | + (TyKind::Param(_), _) | + (TyKind::Infer(_), _) => {} + _ if ty::TyS::same_type(exp_ty, found_ty) => {} + _ => show_suggestion = false, + }; } - } else { - show_suggestion = false; + TyKind::Param(_) | TyKind::Infer(_) => {} + _ => show_suggestion = false, } } if let (Ok(snippet), true) = ( diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index b2e2955619e06..1d30ccb87b5d8 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -658,6 +658,19 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tcx.needs_drop_raw(param_env.and(self)) } + pub fn same_type(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + match (&a.sty, &b.sty) { + (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { + if did_a != did_b { + return false; + } + + substs_a.types().zip(substs_b.types()).all(|(a, b)| Self::same_type(a, b)) + } + _ => a == b, + } + } + /// Check whether a type is representable. This means it cannot contain unboxed /// structural recursion. This check is needed for structs and enums. pub fn is_representable(&'tcx self, @@ -730,19 +743,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } - fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.sty, &b.sty) { - (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { - if did_a != did_b { - return false; - } - - substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type(a, b)) - } - _ => a == b, - } - } - // Does the type `ty` directly (without indirection through a pointer) // contain any types on stack `seen`? fn is_type_structurally_recursive<'a, 'tcx>( @@ -807,7 +807,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // struct Foo { Option<Option<Foo>> } for &seen_type in iter { - if same_type(ty, seen_type) { + if ty::TyS::same_type(ty, seen_type) { debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty); From 87a4d21a8c1ba6cf82730d61fa96b9a08cd55fdb Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas <git@kazlauskas.me> Date: Sun, 30 Dec 2018 00:15:42 +0200 Subject: [PATCH 051/124] Remove mention of required memory to build Because it, obviously, changes all the time and 600MiB is way out-of-date now. --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index dc013a1ad2be6..7eb5e8067eda2 100644 --- a/README.md +++ b/README.md @@ -186,18 +186,15 @@ fetch snapshots, and an OS that can execute the available snapshot binaries. Snapshot binaries are currently built and tested on several platforms: -| Platform / Architecture | x86 | x86_64 | -|--------------------------------|-----|--------| -| Windows (7, 8, Server 2008 R2) | ✓ | ✓ | -| Linux (2.6.18 or later) | ✓ | ✓ | -| OSX (10.7 Lion or later) | ✓ | ✓ | +| Platform / Architecture | x86 | x86_64 | +|--------------------------|-----|--------| +| Windows (7, 8, 10, ...) | ✓ | ✓ | +| Linux (2.6.18 or later) | ✓ | ✓ | +| OSX (10.7 Lion or later) | ✓ | ✓ | You may find that other platforms work, but these are our officially supported build environments that are most likely to work. -Rust currently needs between 600MiB and 1.5GiB of RAM to build, depending on platform. -If it hits swap, it will take a very long time to build. - There is more advice about hacking on Rust in [CONTRIBUTING.md]. [CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md From 111bcb19cc35fd9c8cfb9333132e1cf21a8c7b95 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sun, 30 Dec 2018 00:56:55 +0300 Subject: [PATCH 052/124] Improve error recovery for some built-in macros --- src/libsyntax/ext/base.rs | 9 +++++---- src/libsyntax/ext/source_util.rs | 2 +- src/libsyntax_ext/compile_error.rs | 2 +- src/libsyntax_ext/concat.rs | 7 +++++++ src/libsyntax_ext/concat_idents.rs | 6 +++--- src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/format.rs | 26 +++++++++++++------------ src/test/ui/extenv/issue-55897.rs | 15 ++++++++++++++ src/test/ui/extenv/issue-55897.stderr | 23 ++++++++++++++++++++++ src/test/ui/issues/issue-11692-1.rs | 4 +--- src/test/ui/issues/issue-11692-1.stderr | 14 ++----------- src/test/ui/issues/issue-11692-2.rs | 1 - src/test/ui/issues/issue-11692-2.stderr | 10 +--------- 13 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 src/test/ui/extenv/issue-55897.rs create mode 100644 src/test/ui/extenv/issue-55897.stderr diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7e8b7007b2289..2793754e1033a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -995,7 +995,7 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str, -) -> Result<Spanned<(Symbol, ast::StrStyle)>, DiagnosticBuilder<'a>> { +) -> Result<Spanned<(Symbol, ast::StrStyle)>, Option<DiagnosticBuilder<'a>>> { // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. let expr = expr.map(|mut expr| { expr.span = expr.span.apply_mark(cx.current_expansion.mark); @@ -1007,16 +1007,17 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), - _ => cx.struct_span_err(l.span, err_msg) + _ => Some(cx.struct_span_err(l.span, err_msg)) }, - _ => cx.struct_span_err(expr.span, err_msg) + ast::ExprKind::Err => None, + _ => Some(cx.struct_span_err(expr.span, err_msg)) }) } pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) - .map_err(|mut err| err.emit()) + .map_err(|err| err.map(|mut err| err.emit())) .ok() .map(|s| s.node) } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 1101d7772b839..e63042a420824 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -86,7 +86,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T -> Box<dyn base::MacResult+'cx> { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), }; // The file will be added to the code map by the parser let path = res_rel_file(cx, sp, file); diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs index fd018885a26be..8f7f5deb091ac 100644 --- a/src/libsyntax_ext/compile_error.rs +++ b/src/libsyntax_ext/compile_error.rs @@ -10,7 +10,7 @@ pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt, tts: &[tokenstream::TokenTree]) -> Box<dyn base::MacResult + 'cx> { let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(v) => v, }; diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index a19c7e427e34c..807f190cb6a1a 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -18,6 +18,7 @@ pub fn expand_syntax_ext( }; let mut accumulator = String::new(); let mut missing_literal = vec![]; + let mut has_errors = false; for e in es { match e.node { ast::ExprKind::Lit(ref lit) => match lit.node { @@ -41,6 +42,9 @@ pub fn expand_syntax_ext( cx.span_err(e.span, "cannot concatenate a byte string literal"); } }, + ast::ExprKind::Err => { + has_errors = true; + } _ => { missing_literal.push(e.span); } @@ -50,6 +54,9 @@ pub fn expand_syntax_ext( let mut err = cx.struct_span_err(missing_literal, "expected a literal"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); + return base::DummyResult::expr(sp); + } else if has_errors { + return base::DummyResult::expr(sp); } let sp = sp.apply_mark(cx.current_expansion.mark); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 9c49a59678fdb..de96de4bdc2bc 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -24,7 +24,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, if tts.is_empty() { cx.span_err(sp, "concat_idents! takes 1 or more arguments."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } let mut res_str = String::new(); @@ -34,7 +34,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, TokenTree::Token(_, token::Comma) => {} _ => { cx.span_err(sp, "concat_idents! expecting comma."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } } } else { @@ -43,7 +43,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, res_str.push_str(&ident.as_str()), _ => { cx.span_err(sp, "concat_idents! requires ident args."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } } } diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 33669c8bc37ec..16fb64a5f3912 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -79,7 +79,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); - cx.expr_usize(sp, 0) + return DummyResult::expr(sp); } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 95bb8c886abf2..ac1402a0faaa5 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -748,18 +748,20 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, fmt } Ok(fmt) => fmt, - Err(mut err) => { - let sugg_fmt = match args.len() { - 0 => "{}".to_string(), - _ => format!("{}{{}}", "{} ".repeat(args.len())), - }; - err.span_suggestion_with_applicability( - fmt_sp.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{}\", ", sugg_fmt), - Applicability::MaybeIncorrect, - ); - err.emit(); + Err(err) => { + if let Some(mut err) = err { + let sugg_fmt = match args.len() { + 0 => "{}".to_string(), + _ => format!("{}{{}}", "{} ".repeat(args.len())), + }; + err.span_suggestion_with_applicability( + fmt_sp.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{}\", ", sugg_fmt), + Applicability::MaybeIncorrect, + ); + err.emit(); + } return DummyResult::raw_expr(sp, true); } }; diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs new file mode 100644 index 0000000000000..bd151c8a4e4e7 --- /dev/null +++ b/src/test/ui/extenv/issue-55897.rs @@ -0,0 +1,15 @@ +use prelude::*; //~ ERROR unresolved import `prelude` + +mod unresolved_env { + use env; + + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR cannot determine resolution for the macro `env` +} + +mod nonexistent_env { + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR environment variable `NON_EXISTENT` not defined +} + +fn main() {} diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr new file mode 100644 index 0000000000000..4d2e35dff4629 --- /dev/null +++ b/src/test/ui/extenv/issue-55897.stderr @@ -0,0 +1,23 @@ +error: environment variable `NON_EXISTENT` not defined + --> $DIR/issue-55897.rs:11:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0432]: unresolved import `prelude` + --> $DIR/issue-55897.rs:1:5 + | +LL | use prelude::*; //~ ERROR unresolved import `prelude` + | ^^^^^^^ did you mean `std::prelude`? + +error: cannot determine resolution for the macro `env` + --> $DIR/issue-55897.rs:6:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs index 2277778040292..70b712c560830 100644 --- a/src/test/ui/issues/issue-11692-1.rs +++ b/src/test/ui/issues/issue-11692-1.rs @@ -1,5 +1,3 @@ fn main() { - print!(testo!()); - //~^ ERROR: format argument must be a string literal - //~| ERROR: cannot find macro `testo!` in this scope + print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope } diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr index f4cc825803a3b..57a6a999544cf 100644 --- a/src/test/ui/issues/issue-11692-1.stderr +++ b/src/test/ui/issues/issue-11692-1.stderr @@ -1,18 +1,8 @@ -error: format argument must be a string literal - --> $DIR/issue-11692-1.rs:2:12 - | -LL | print!(testo!()); - | ^^^^^^^^ -help: you might be missing a string literal to format with - | -LL | print!("{}", testo!()); - | ^^^^^ - error: cannot find macro `testo!` in this scope --> $DIR/issue-11692-1.rs:2:12 | -LL | print!(testo!()); +LL | print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope | ^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs index 6103931657342..61be284d7320e 100644 --- a/src/test/ui/issues/issue-11692-2.rs +++ b/src/test/ui/issues/issue-11692-2.rs @@ -1,4 +1,3 @@ fn main() { concat!(test!()); //~ ERROR cannot find macro `test!` in this scope - //~| ERROR expected a literal } diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr index 848415435a78b..5d4467080f149 100644 --- a/src/test/ui/issues/issue-11692-2.stderr +++ b/src/test/ui/issues/issue-11692-2.stderr @@ -1,16 +1,8 @@ -error: expected a literal - --> $DIR/issue-11692-2.rs:2:13 - | -LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope - | ^^^^^^^ - | - = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` - error: cannot find macro `test!` in this scope --> $DIR/issue-11692-2.rs:2:13 | LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope | ^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error From a5b93f006927e105ccfeb89dfd0e21846864dea2 Mon Sep 17 00:00:00 2001 From: Czipperz <czipperz@gmail.com> Date: Sat, 29 Dec 2018 17:48:43 -0500 Subject: [PATCH 053/124] Make std::cmp::Ord documentation specify what it means to agree with PartialEq --- src/libcore/cmp.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9336b130d1bb2..8eff9a8c8a26a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -472,9 +472,10 @@ impl<T: Ord> Ord for Reverse<T> { /// Then you must define an implementation for `cmp()`. You may find it useful to use /// `cmp()` on your type's fields. /// -/// Implementations of `PartialEq`, `PartialOrd`, and `Ord` *must* agree with each other. It's -/// easy to accidentally make them disagree by deriving some of the traits and manually -/// implementing others. +/// Implementations of `PartialEq`, `PartialOrd`, and `Ord` *must* +/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if +/// and only if `a == b`. It's easy to accidentally make them disagree +/// by deriving some of the traits and manually implementing others. /// /// Here's an example where you want to sort people by height only, disregarding `id` /// and `name`: From 6090b316c1006aee8d72de121e6f6f11c76b9770 Mon Sep 17 00:00:00 2001 From: Czipperz <czipperz@gmail.com> Date: Sat, 29 Dec 2018 19:14:06 -0500 Subject: [PATCH 054/124] Specify criterion for PartialOrd --- src/libcore/cmp.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 8eff9a8c8a26a..f420d0d00a401 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -474,8 +474,9 @@ impl<T: Ord> Ord for Reverse<T> { /// /// Implementations of `PartialEq`, `PartialOrd`, and `Ord` *must* /// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if -/// and only if `a == b`. It's easy to accidentally make them disagree -/// by deriving some of the traits and manually implementing others. +/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for +/// all `a` and `b`. It's easy to accidentally make them disagree by +/// deriving some of the traits and manually implementing others. /// /// Here's an example where you want to sort people by height only, disregarding `id` /// and `name`: From faaae93788ba2e1ca17634692d50944e3bbc08ef Mon Sep 17 00:00:00 2001 From: Czipperz <czipperz@gmail.com> Date: Sat, 29 Dec 2018 02:54:05 -0500 Subject: [PATCH 055/124] Mention ToString in std::fmt docs --- src/liballoc/fmt.rs | 4 ++++ src/liballoc/macros.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 73e2c4494feef..a1e7533449c69 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -27,6 +27,9 @@ //! will then parse the format string and determine if the list of arguments //! provided is suitable to pass to this format string. //! +//! To convert a single value to a string, use the [`to_string`] method. This +//! will use the [`Display`] formatting trait. +//! //! ## Positional parameters //! //! Each formatting argument is allowed to specify which value argument it's @@ -487,6 +490,7 @@ //! [`write!`]: ../../std/macro.write.html //! [`Debug`]: trait.Debug.html //! [`format!`]: ../../std/macro.format.html +//! [`to_string`]: ../../std/string/trait.ToString.html //! [`writeln!`]: ../../std/macro.writeln.html //! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt //! [`std::io::Write`]: ../../std/io/trait.Write.html diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 1978efda097f2..db91b07fa71b4 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -73,9 +73,14 @@ macro_rules! vec { /// The same convention is used with [`print!`] and [`write!`] macros, /// depending on the intended destination of the string. /// +/// To convert a single value to a string, use the [`to_string`] method. This +/// will use the [`Display`] formatting trait. +/// /// [fmt]: ../std/fmt/index.html /// [`print!`]: ../std/macro.print.html /// [`write!`]: ../std/macro.write.html +/// [`to_string`]: ../std/string/trait.ToString.html +/// [`Display`]: ../std/fmt/trait.Display.html /// /// # Panics /// From c22ee1aab6dfa1f8a1766cd0696cb5ed2116d663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Sat, 29 Dec 2018 16:35:57 -0800 Subject: [PATCH 056/124] Do not complain about missing crate named as a keyword --- src/librustc_resolve/lib.rs | 10 ++++++++-- src/librustc_resolve/macros.rs | 6 ++++-- src/librustc_resolve/resolve_imports.rs | 6 +++++- src/test/ui/issues/issue-57198-pass.rs | 9 +++++++++ src/test/ui/issues/issue-57198.rs | 8 ++++++++ src/test/ui/issues/issue-57198.stderr | 8 ++++++++ 6 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-57198-pass.rs create mode 100644 src/test/ui/issues/issue-57198.rs create mode 100644 src/test/ui/issues/issue-57198.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d16e097e3a52e..3d81c75f1fd5e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1034,6 +1034,8 @@ enum PathResult<'a> { NonModule(PathResolution), Indeterminate, Failed(Span, String, bool /* is the error from the last segment? */), + /// Encountered an error that is reported elsewhere + Ignore, } enum ModuleKind { @@ -1759,6 +1761,7 @@ impl<'a> Resolver<'a> { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); Def::Err } + PathResult::Ignore => Def::Err, }; let segments: Vec<_> = segments.iter().map(|seg| { @@ -3684,7 +3687,7 @@ impl<'a> Resolver<'a> { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } - PathResult::Module(..) | PathResult::Failed(..) => return None, + PathResult::Module(..) | PathResult::Failed(..) | PathResult::Ignore => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; @@ -3916,8 +3919,11 @@ impl<'a> Resolver<'a> { }); if let Some(candidate) = candidates.get(0) { format!("did you mean `{}`?", candidate.path) - } else { + } else if !ident.is_used_keyword() { format!("maybe a missing `extern crate {};`?", ident) + } else { + // the parser will already have complained about the keyword being used + return PathResult::Ignore; } } else if i == 0 { format!("use of undeclared type or module `{}`", ident) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 7585076bc75f6..6cb1be4a3064f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -365,7 +365,8 @@ impl<'a> Resolver<'a> { Ok(path_res.base_def()) } PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => { + PathResult::NonModule(..) | PathResult::Indeterminate | + PathResult::Failed(..) | PathResult::Ignore => { Err(Determinacy::Determined) } PathResult::Module(..) => unreachable!(), @@ -930,7 +931,8 @@ impl<'a> Resolver<'a> { let def = path_res.base_def(); check_consistency(self, &path, path_span, kind, initial_def, def); } - path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => { + path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) | + path_res @ PathResult::Ignore => { let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res { (span, msg) } else { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c84dbd2974624..5da88a5c2fe8f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -774,7 +774,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { match path_res { PathResult::Module(module) => module, PathResult::Indeterminate => return false, - PathResult::NonModule(..) | PathResult::Failed(..) => return true, + PathResult::NonModule(..) | PathResult::Failed(..) | + PathResult::Ignore => return true, } }; @@ -868,6 +869,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { module } + PathResult::Ignore => { + return None; + } PathResult::Failed(span, msg, false) => { if no_ambiguity { assert!(directive.imported_module.get().is_none()); diff --git a/src/test/ui/issues/issue-57198-pass.rs b/src/test/ui/issues/issue-57198-pass.rs new file mode 100644 index 0000000000000..3857def9824f8 --- /dev/null +++ b/src/test/ui/issues/issue-57198-pass.rs @@ -0,0 +1,9 @@ +// run-pass + +mod m { + pub fn r#for() {} +} + +fn main() { + m::r#for(); +} diff --git a/src/test/ui/issues/issue-57198.rs b/src/test/ui/issues/issue-57198.rs new file mode 100644 index 0000000000000..714a46cbc9f48 --- /dev/null +++ b/src/test/ui/issues/issue-57198.rs @@ -0,0 +1,8 @@ +mod m { + pub fn r#for() {} +} + +fn main() { + m::for(); + //~^ ERROR expected identifier, found keyword `for` +} diff --git a/src/test/ui/issues/issue-57198.stderr b/src/test/ui/issues/issue-57198.stderr new file mode 100644 index 0000000000000..c4d297b2d95eb --- /dev/null +++ b/src/test/ui/issues/issue-57198.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found keyword `for` + --> $DIR/issue-57198.rs:6:8 + | +LL | m::for(); + | ^^^ expected identifier, found keyword + +error: aborting due to previous error + From cceb1f72fe0753c6f400950566045dac1d42b838 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Fri, 16 Nov 2018 22:56:18 +0100 Subject: [PATCH 057/124] Refactor `UserTypeAnnotation`. This commit refactors the `UserTypeAnnotation` type to be referred to by an index within `UserTypeProjection`. `UserTypeAnnotation` is instead kept in an `IndexVec` within the `Mir` struct. Further, instead of `UserTypeAnnotation` containing canonicalized types, it now contains normal types and the entire `UserTypeAnnotation` is canonicalized. To support this, the type was moved from the `rustc::mir` module to `rustc::ty` module. --- src/librustc/ich/impls_mir.rs | 17 -- src/librustc/ich/impls_ty.rs | 26 ++++ src/librustc/mir/mod.rs | 50 ++---- src/librustc/mir/visit.rs | 24 +-- src/librustc/ty/context.rs | 146 +++++++++++++----- src/librustc/ty/mod.rs | 4 + src/librustc/ty/subst.rs | 40 +---- src/librustc_mir/borrow_check/nll/renumber.rs | 14 +- .../borrow_check/nll/type_check/mod.rs | 88 +++++++---- src/librustc_mir/build/expr/as_constant.rs | 15 +- src/librustc_mir/build/expr/as_place.rs | 10 +- src/librustc_mir/build/expr/as_rvalue.rs | 3 + src/librustc_mir/build/matches/mod.rs | 14 +- src/librustc_mir/build/mod.rs | 3 + src/librustc_mir/hair/cx/block.rs | 5 +- src/librustc_mir/hair/cx/expr.rs | 63 +++++--- src/librustc_mir/hair/mod.rs | 13 +- src/librustc_mir/hair/pattern/mod.rs | 73 +++++---- src/librustc_mir/hair/util.rs | 34 ++-- src/librustc_mir/shim.rs | 4 + src/librustc_mir/transform/promote_consts.rs | 1 + src/librustc_traits/type_op.rs | 30 +--- src/librustc_typeck/check/mod.rs | 101 ++++++------ src/librustc_typeck/check/writeback.rs | 29 ++-- src/test/mir-opt/basic_assignment.rs | 2 +- .../dump-adt-brace-struct.stderr | 2 +- .../user-annotations/dump-fn-method.stderr | 20 +-- 27 files changed, 476 insertions(+), 355 deletions(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index dbabff9ee88c2..002ac7cc7a9bb 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -494,22 +494,5 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubj impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted }); -impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<'gcx> { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher<W>) { - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - mir::UserTypeAnnotation::Ty(ref ty) => { - ty.hash_stable(hcx, hasher); - } - mir::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => { - def_id.hash_stable(hcx, hasher); - substs.hash_stable(hcx, hasher); - } - } - } -} - impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base, projs }); impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents }); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 65b8f04e30a12..b2fe4b7561c5a 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1251,3 +1251,29 @@ impl_stable_hash_for!( goal, } ); + +impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotation<'gcx> { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + ty::UserTypeAnnotation::Ty(ref ty) => { + ty.hash_stable(hcx, hasher); + } + ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => { + def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + } + } + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotationIndex { + #[inline] + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + self.index().hash_stable(hcx, hasher); + } +} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 36d51c5971278..ecbe14c093f40 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -27,9 +27,12 @@ use syntax::ast::{self, Name}; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use ty::subst::{CanonicalUserSubsts, Subst, Substs}; -use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; +use ty::subst::{Subst, Substs}; use ty::layout::VariantIdx; +use ty::{ + self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, + UserTypeAnnotationIndex, UserTypeAnnotation, +}; use util::ppaux; pub use mir::interpret::AssertMessage; @@ -121,6 +124,9 @@ pub struct Mir<'tcx> { /// variables and temporaries. pub local_decls: LocalDecls<'tcx>, + /// User type annotations + pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, + /// Number of arguments this function takes. /// /// Starting at local 1, `arg_count` locals will be provided by the caller @@ -161,7 +167,8 @@ impl<'tcx> Mir<'tcx> { source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>, promoted: IndexVec<Promoted, Mir<'tcx>>, yield_ty: Option<Ty<'tcx>>, - local_decls: IndexVec<Local, LocalDecl<'tcx>>, + local_decls: LocalDecls<'tcx>, + user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, upvar_decls: Vec<UpvarDecl>, span: Span, @@ -185,6 +192,7 @@ impl<'tcx> Mir<'tcx> { generator_drop: None, generator_layout: None, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg: None, @@ -418,6 +426,7 @@ impl_stable_hash_for!(struct Mir<'tcx> { generator_drop, generator_layout, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg, @@ -2232,7 +2241,7 @@ pub enum AggregateKind<'tcx> { &'tcx AdtDef, VariantIdx, &'tcx Substs<'tcx>, - Option<UserTypeAnnotation<'tcx>>, + Option<UserTypeAnnotationIndex>, Option<usize>, ), @@ -2446,38 +2455,11 @@ pub struct Constant<'tcx> { /// indicate that `Vec<_>` was explicitly specified. /// /// Needed for NLL to impose user-given type constraints. - pub user_ty: Option<UserTypeAnnotation<'tcx>>, + pub user_ty: Option<UserTypeAnnotationIndex>, pub literal: &'tcx ty::Const<'tcx>, } -/// A user-given type annotation attached to a constant. These arise -/// from constants that are named via paths, like `Foo::<A>::new` and -/// so forth. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub enum UserTypeAnnotation<'tcx> { - Ty(CanonicalTy<'tcx>), - - /// The canonical type is the result of `type_of(def_id)` with the - /// given substitutions applied. - TypeOf(DefId, CanonicalUserSubsts<'tcx>), -} - -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> { - (UserTypeAnnotation::Ty)(ty), - (UserTypeAnnotation::TypeOf)(def, substs), - } -} - -EnumLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> { - type Lifted = UserTypeAnnotation<'tcx>; - (UserTypeAnnotation::Ty)(ty), - (UserTypeAnnotation::TypeOf)(def, substs), - } -} - /// A collection of projections into user types. /// /// They are projections because a binding can occur a part of a @@ -2556,7 +2538,7 @@ impl<'tcx> UserTypeProjections<'tcx> { /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UserTypeProjection<'tcx> { - pub base: UserTypeAnnotation<'tcx>, + pub base: UserTypeAnnotationIndex, pub projs: Vec<ProjectionElem<'tcx, (), ()>>, } @@ -2970,6 +2952,7 @@ CloneTypeFoldableAndLiftImpls! { SourceScope, SourceScopeData, SourceScopeLocalData, + UserTypeAnnotationIndex, } BraceStructTypeFoldableImpl! { @@ -2983,6 +2966,7 @@ BraceStructTypeFoldableImpl! { generator_drop, generator_layout, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg, diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index a20b8231f88a2..67f85fbc8679e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,4 +1,5 @@ use hir::def_id::DefId; +use infer::canonical::Canonical; use ty::subst::Substs; use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty}; use mir::*; @@ -219,9 +220,10 @@ macro_rules! make_mir_visitor { fn visit_user_type_annotation( &mut self, - ty: & $($mutability)* UserTypeAnnotation<'tcx>, + index: UserTypeAnnotationIndex, + ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>, ) { - self.super_user_type_annotation(ty); + self.super_user_type_annotation(index, ty); } fn visit_region(&mut self, @@ -307,6 +309,14 @@ macro_rules! make_mir_visitor { self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]); } + for index in mir.user_type_annotations.indices() { + let (span, annotation) = & $($mutability)* mir.user_type_annotations[index]; + self.visit_user_type_annotation( + index, annotation + ); + self.visit_span(span); + } + self.visit_span(&$($mutability)* mir.span); } @@ -865,18 +875,14 @@ macro_rules! make_mir_visitor { fn super_user_type_projection( &mut self, - ty: & $($mutability)* UserTypeProjection<'tcx>, + _ty: & $($mutability)* UserTypeProjection<'tcx>, ) { - let UserTypeProjection { - ref $($mutability)* base, - projs: _, // Note: Does not visit projection elems! - } = *ty; - self.visit_user_type_annotation(base); } fn super_user_type_annotation( &mut self, - _ty: & $($mutability)* UserTypeAnnotation<'tcx>, + _index: UserTypeAnnotationIndex, + _ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>, ) { } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ea69d466ba6c5..32348e2e5046d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,7 +14,7 @@ use hir::map as hir_map; use hir::map::DefPathHash; use lint::{self, Lint}; use ich::{StableHashingContext, NodeIdHashingMode}; -use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; +use infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use infer::outlives::free_region_map::FreeRegionMap; use middle::cstore::CrateStoreDyn; use middle::cstore::EncodedMetadata; @@ -23,7 +23,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret, ProjectionKind}; use mir::interpret::Allocation; -use ty::subst::{CanonicalUserSubsts, Kind, Substs, Subst}; +use ty::subst::{Kind, Substs, Subst}; use ty::ReprOptions; use traits; use traits::{Clause, Clauses, GoalKind, Goal, Goals}; @@ -38,8 +38,8 @@ use ty::GenericParamDefKind; use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; use ty::query; use ty::steal::Steal; -use ty::BindingMode; -use ty::CanonicalTy; +use ty::subst::{UserSubsts, UnpackedKind}; +use ty::{BoundVar, BindingMode}; use ty::CanonicalPolyFnSig; use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; @@ -49,7 +49,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; use arena::{TypedArena, SyncDroplessArena}; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal}; use std::any::Any; use std::borrow::Borrow; @@ -342,26 +342,21 @@ pub struct TypeckTables<'tcx> { /// other items. node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, - /// Stores the canonicalized types provided by the user. See also - /// `AscribeUserType` statement in MIR. - user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>, + /// This will either store the canonicalized types provided by the user + /// or the substitutions that the user explicitly gave (if any) attached + /// to `id`. These will not include any inferred values. The canonical form + /// is used to capture things like `_` or other unspecified values. + /// + /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the + /// canonical substitutions would include only `for<X> { Vec<X> }`. + /// + /// See also `AscribeUserType` statement in MIR. + user_provided_types: ItemLocalMap<CanonicalUserTypeAnnotation<'tcx>>, /// Stores the canonicalized types provided by the user. See also /// `AscribeUserType` statement in MIR. pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>, - /// Stores the substitutions that the user explicitly gave (if any) - /// attached to `id`. These will not include any inferred - /// values. The canonical form is used to capture things like `_` - /// or other unspecified values. - /// - /// Example: - /// - /// If the user wrote `foo.collect::<Vec<_>>()`, then the - /// canonical substitutions would include only `for<X> { Vec<X> - /// }`. - user_substs: ItemLocalMap<CanonicalUserSubsts<'tcx>>, - adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>, /// Stores the actual binding mode for all instances of hir::BindingAnnotation. @@ -432,11 +427,10 @@ impl<'tcx> TypeckTables<'tcx> { local_id_root, type_dependent_defs: Default::default(), field_indices: Default::default(), - user_provided_tys: Default::default(), + user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), node_substs: Default::default(), - user_substs: Default::default(), adjustments: Default::default(), pat_binding_modes: Default::default(), pat_adjustments: Default::default(), @@ -491,17 +485,21 @@ impl<'tcx> TypeckTables<'tcx> { } } - pub fn user_provided_tys(&self) -> LocalTableInContext<'_, CanonicalTy<'tcx>> { + pub fn user_provided_types( + &self + ) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> { LocalTableInContext { local_id_root: self.local_id_root, - data: &self.user_provided_tys + data: &self.user_provided_types } } - pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalTy<'tcx>> { + pub fn user_provided_types_mut( + &mut self + ) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> { LocalTableInContextMut { local_id_root: self.local_id_root, - data: &mut self.user_provided_tys + data: &mut self.user_provided_types } } @@ -551,18 +549,6 @@ impl<'tcx> TypeckTables<'tcx> { self.node_substs.get(&id.local_id).cloned() } - pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalUserSubsts<'tcx>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.user_substs - } - } - - pub fn user_substs(&self, id: hir::HirId) -> Option<CanonicalUserSubsts<'tcx>> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); - self.user_substs.get(&id.local_id).cloned() - } - // Returns the type of a pattern as a monotype. Like @expr_ty, this function // doesn't provide type parameter substitutions. pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { @@ -739,11 +725,10 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> { local_id_root, ref type_dependent_defs, ref field_indices, - ref user_provided_tys, + ref user_provided_types, ref user_provided_sigs, ref node_types, ref node_substs, - ref user_substs, ref adjustments, ref pat_binding_modes, ref pat_adjustments, @@ -763,11 +748,10 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { type_dependent_defs.hash_stable(hcx, hasher); field_indices.hash_stable(hcx, hasher); - user_provided_tys.hash_stable(hcx, hasher); + user_provided_types.hash_stable(hcx, hasher); user_provided_sigs.hash_stable(hcx, hasher); node_types.hash_stable(hcx, hasher); node_substs.hash_stable(hcx, hasher); - user_substs.hash_stable(hcx, hasher); adjustments.hash_stable(hcx, hasher); pat_binding_modes.hash_stable(hcx, hasher); pat_adjustments.hash_stable(hcx, hasher); @@ -805,6 +789,84 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> { } } +newtype_index! { + pub struct UserTypeAnnotationIndex { + DEBUG_FORMAT = "UserTypeAnnotation({})", + const START_INDEX = 0, + } +} + +/// Mapping of type annotation indices to canonical user type annotations. +pub type CanonicalUserTypeAnnotations<'tcx> = + IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>; + +/// Canonicalized user type annotation. +pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>; + +impl CanonicalUserTypeAnnotation<'gcx> { + /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`, + /// i.e. each thing is mapped to a canonical variable with the same index. + pub fn is_identity(&self) -> bool { + match self.value { + UserTypeAnnotation::Ty(_) => false, + UserTypeAnnotation::TypeOf(_, user_substs) => { + if user_substs.user_self_ty.is_some() { + return false; + } + + user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { + match kind.unpack() { + UnpackedKind::Type(ty) => match ty.sty { + ty::Bound(debruijn, b) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(debruijn, ty::INNERMOST); + cvar == b.var + } + _ => false, + }, + + UnpackedKind::Lifetime(r) => match r { + ty::ReLateBound(debruijn, br) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(*debruijn, ty::INNERMOST); + cvar == br.assert_bound_var() + } + _ => false, + }, + } + }) + }, + } + } +} + +/// A user-given type annotation attached to a constant. These arise +/// from constants that are named via paths, like `Foo::<A>::new` and +/// so forth. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +pub enum UserTypeAnnotation<'tcx> { + Ty(Ty<'tcx>), + + /// The canonical type is the result of `type_of(def_id)` with the + /// given substitutions applied. + TypeOf(DefId, UserSubsts<'tcx>), +} + +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> { + (UserTypeAnnotation::Ty)(ty), + (UserTypeAnnotation::TypeOf)(def, substs), + } +} + +EnumLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> { + type Lifted = UserTypeAnnotation<'tcx>; + (UserTypeAnnotation::Ty)(ty), + (UserTypeAnnotation::TypeOf)(def, substs), + } +} + impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8348aa8a95612..d40dd830e9fb9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -73,6 +73,10 @@ pub use self::binding::BindingMode::*; pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local}; pub use self::context::{Lift, TypeckTables, CtxtInterners}; +pub use self::context::{ + UserTypeAnnotationIndex, UserTypeAnnotation, CanonicalUserTypeAnnotation, + CanonicalUserTypeAnnotations, +}; pub use self::instance::{Instance, InstanceDef}; diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 560e80abb9cbd..64e7af815b4bf 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -2,12 +2,11 @@ use hir::def_id::DefId; use infer::canonical::Canonical; -use ty::{self, BoundVar, Lift, List, Ty, TyCtxt}; +use ty::{self, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; -use rustc_data_structures::indexed_vec::Idx; use smallvec::SmallVec; use core::intrinsics; @@ -559,43 +558,6 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>; -impl CanonicalUserSubsts<'tcx> { - /// True if this represents a substitution like - /// - /// ```text - /// [?0, ?1, ?2] - /// ``` - /// - /// i.e., each thing is mapped to a canonical variable with the same index. - pub fn is_identity(&self) -> bool { - if self.value.user_self_ty.is_some() { - return false; - } - - self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { - match kind.unpack() { - UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(debruijn, b) => { - // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(debruijn, ty::INNERMOST); - cvar == b.var - } - _ => false, - }, - - UnpackedKind::Lifetime(r) => match r { - ty::ReLateBound(debruijn, br) => { - // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(*debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() - } - _ => false, - }, - } - }) - } -} - /// Stores the user-given substs to reach some fully qualified path /// (e.g., `<T>::Item` or `<T as Trait>::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 673ee4ec017ac..55af7399aab8f 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,10 @@ +use rustc::infer::canonical::Canonical; use rustc::ty::subst::Substs; -use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{Location, Mir, UserTypeAnnotation}; +use rustc::ty::{ + self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, UserTypeAnnotation, + UserTypeAnnotationIndex, +}; +use rustc::mir::{Location, Mir}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -55,7 +59,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_ty: ty={:?}", ty); } - fn visit_user_type_annotation(&mut self, _ty: &mut UserTypeAnnotation<'tcx>) { + fn visit_user_type_annotation( + &mut self, + _index: UserTypeAnnotationIndex, + _ty: &mut Canonical<'tcx, UserTypeAnnotation<'tcx>>, + ) { // User type annotations represent the types that the user // wrote in the progarm. We don't want to erase the regions // from these types: rather, we want to add them as diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6d2fb54587ea3..8f8abe09810a2 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -36,7 +36,10 @@ use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; -use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; +use rustc::ty::{ + self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserTypeAnnotation, + UserTypeAnnotationIndex, +}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::ty::layout::VariantIdx; @@ -272,19 +275,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_constant(constant, location); self.sanitize_type(constant, constant.ty); - if let Some(user_ty) = constant.user_ty { + if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( constant.ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty, projs: vec![], }, + &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { + let annotation = self.cx.instantiated_type_annotations[&annotation_index]; span_mirbug!( self, constant, "bad constant user type {:?} vs {:?}: {:?}", - user_ty, + annotation, constant.ty, terr, ); @@ -715,6 +719,15 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>, + /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create + /// an "instantiated" version at the beginning of type check, which replaces each + /// canonical variable with a fresh inference variable. These instantiated versions are + /// stored either in this field or in user_substs, depending on the kind of user-type + /// annotation. They are then referenced by the code which has the job of enforcing these + /// annotations. Part of the reason for this setup is that it allows us to enforce basic + /// WF criteria on the types even if the code that referenced them is dead + /// code (see #54943). + instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserTypeAnnotation<'tcx>>, } struct BorrowCheckContext<'a, 'tcx: 'a> { @@ -860,7 +873,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>, ) -> Self { - TypeChecker { + let mut checker = Self { infcx, last_span: DUMMY_SP, mir, @@ -871,7 +884,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, + instantiated_type_annotations: Default::default(), + }; + checker.instantiate_user_type_annotations(); + checker + } + + /// Instantiate canonical types from user type annotations in the `Mir` into the + /// `TypeChecker`. Used when relating user type annotations and when checking if + /// annotations are well-formed. + fn instantiate_user_type_annotations(&mut self) { + debug!( + "instantiate_user_type_annotations: user_type_annotations={:?}", + self.mir.user_type_annotations + ); + for annotation_index in self.mir.user_type_annotations.indices() { + let (span, canonical_annotation) = &self.mir.user_type_annotations[annotation_index]; + let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( + *span, &canonical_annotation + ); + match annotation { + UserTypeAnnotation::Ty(ref mut ty) => + *ty = self.normalize(ty, Locations::All(*span)), + _ => {}, + } + self.instantiated_type_annotations.insert(annotation_index, annotation); } + debug!( + "instantiate_user_type_annotations: instantiated_type_annotations={:?}", + self.instantiated_type_annotations, + ); } /// Given some operation `op` that manipulates types, proves @@ -1003,18 +1045,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - match user_ty.base { - UserTypeAnnotation::Ty(canonical_ty) => { - let (ty, _) = self.infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty); - + match self.instantiated_type_annotations[&user_ty.base] { + UserTypeAnnotation::Ty(ty) => { // The `TypeRelating` code assumes that "unresolved inference // variables" appear in the "a" side, so flip `Contravariant` // ambient variance to get the right relationship. let v1 = ty::Contravariant.xform(v); - let tcx = self.infcx.tcx; - let ty = self.normalize(ty, locations); // We need to follow any provided projetions into the type. // @@ -1048,13 +1085,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.relate_types(ty, v1, a, locations, category)?; } } - UserTypeAnnotation::TypeOf(def_id, canonical_substs) => { - let ( - user_substs, - _, - ) = self.infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs); - + UserTypeAnnotation::TypeOf(def_id, user_substs) => { let projs = self.infcx.tcx.intern_projs(&user_ty.projs); self.fully_perform_op( locations, @@ -1225,19 +1256,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } - if let Some(user_ty) = self.rvalue_user_ty(rv) { + if let Some(annotation_index) = self.rvalue_user_ty(rv) { if let Err(terr) = self.relate_type_and_user_type( rv_ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty, projs: vec![], }, + &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { + let annotation = self.instantiated_type_annotations[&annotation_index]; span_mirbug!( self, stmt, "bad user type on rvalue ({:?} = {:?}): {:?}", - user_ty, + annotation, rv_ty, terr ); @@ -1282,21 +1314,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); }; } - StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => { + StatementKind::AscribeUserType(ref place, variance, box ref projection) => { let place_ty = place.ty(mir, tcx).to_ty(tcx); if let Err(terr) = self.relate_type_and_user_type( place_ty, variance, - c_ty, + projection, Locations::All(stmt.source_info.span), ConstraintCategory::TypeAnnotation, ) { + let annotation = self.instantiated_type_annotations[&projection.base]; span_mirbug!( self, stmt, - "bad type assert ({:?} <: {:?}): {:?}", + "bad type assert ({:?} <: {:?} with projections {:?}): {:?}", place_ty, - c_ty, + annotation, + projection.projs, terr ); } @@ -1955,7 +1989,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { /// If this rvalue supports a user-given type annotation, then /// extract and return it. This represents the final type of the /// rvalue and will be unified with the inferred type. - fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotation<'tcx>> { + fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> { match rvalue { Rvalue::Use(_) | Rvalue::Repeat(..) diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a5fbe566a4a73..a431bfc61b37a 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -29,11 +29,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { lint_level: _, value, } => this.as_constant(value), - ExprKind::Literal { literal, user_ty } => Constant { - span, - ty, - user_ty, - literal, + ExprKind::Literal { literal, user_ty } => { + let user_ty = user_ty.map(|ty| { + this.canonical_user_type_annotations.push((span, ty)) + }); + Constant { + span, + ty, + user_ty, + literal, + } }, _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index d651b6bdca01f..3ed00d5797907 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -133,6 +133,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::PlaceTypeAscription { source, user_ty } => { let place = unpack!(block = this.as_place(block, source)); if let Some(user_ty) = user_ty { + let annotation_index = this.canonical_user_type_annotations.push( + (source_info.span, user_ty) + ); this.cfg.push( block, Statement { @@ -140,7 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( place.clone(), Variance::Invariant, - box UserTypeProjection { base: user_ty, projs: vec![], }, + box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); @@ -153,6 +156,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block = this.as_temp(block, source.temp_lifetime, source, mutability) ); if let Some(user_ty) = user_ty { + let annotation_index = this.canonical_user_type_annotations.push( + (source_info.span, user_ty) + ); this.cfg.push( block, Statement { @@ -160,7 +166,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( Place::Local(temp.clone()), Variance::Invariant, - box UserTypeProjection { base: user_ty, projs: vec![], }, + box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2f0e06cd4da29..7dcac05e702a3 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -331,6 +331,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .collect() }; + let user_ty = user_ty.map(|ty| { + this.canonical_user_type_annotations.push((expr_span, ty)) + }); let adt = box AggregateKind::Adt( adt_def, variant_index, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 86dbf1422738a..92642dff3dc68 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -302,6 +302,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let ty_source_info = self.source_info(user_ty_span); + let user_ty = box pat_ascription_ty.user_ty( + &mut self.canonical_user_type_annotations, ty_source_info.span + ); self.cfg.push( block, Statement { @@ -309,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( place, ty::Variance::Invariant, - box pat_ascription_ty.user_ty(), + user_ty, ), }, ); @@ -1314,6 +1317,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ascription.user_ty, ); + let user_ty = box ascription.user_ty.clone().user_ty( + &mut self.canonical_user_type_annotations, source_info.span + ); self.cfg.push( block, Statement { @@ -1321,7 +1327,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( ascription.source.clone(), ty::Variance::Covariant, - box ascription.user_ty.clone().user_ty(), + user_ty, ), }, ); @@ -1484,10 +1490,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()), BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()), }; + let user_ty = user_var_ty.clone().user_ty(&mut self.canonical_user_type_annotations); + debug!("declare_binding: user_ty={:?}", user_ty); let local = LocalDecl::<'tcx> { mutability, ty: var_ty, - user_ty: user_var_ty.clone().user_ty(), + user_ty, name: Some(name), source_info, visibility_scope, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a700963749f67..8acdecf6fa248 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -379,6 +379,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// (A match binding can have two locals; the 2nd is for the arm's guard.) var_indices: NodeMap<LocalsForNode>, local_decls: IndexVec<Local, LocalDecl<'tcx>>, + canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, upvar_decls: Vec<UpvarDecl>, unit_temp: Option<Place<'tcx>>, @@ -812,6 +813,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { LocalDecl::new_return_place(return_ty, return_span), 1, ), + canonical_user_type_annotations: IndexVec::new(), upvar_decls, var_indices: Default::default(), unit_temp: None, @@ -845,6 +847,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { IndexVec::new(), yield_ty, self.local_decls, + self.canonical_user_type_annotations, self.arg_count, self.upvar_decls, self.fn_span, diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 91568f7ff6b58..e73cc40c8c6e4 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -78,12 +78,13 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let mut pattern = cx.pattern_from_hir(&local.pat); if let Some(ty) = &local.ty { - if let Some(&user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) { + if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) { + debug!("mirror_stmts: user_ty={:?}", user_ty); pattern = Pattern { ty: pattern.ty, span: pattern.span, kind: Box::new(PatternKind::AscribeUserType { - user_ty: PatternTypeProjection::from_canonical_ty(user_ty), + user_ty: PatternTypeProjection::from_user_type(user_ty), user_ty_span: ty.span, subpattern: pattern }) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 7b1ed2b0b26ea..293058a0f26f5 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -11,7 +11,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; use rustc::hir::def_id::LocalDefId; -use rustc::mir::{BorrowKind}; +use rustc::mir::BorrowKind; use syntax_pos::Span; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -283,9 +283,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; if let Some((adt_def, index)) = adt_data { let substs = cx.tables().node_substs(fun.hir_id); - - let user_ty = cx.tables().user_substs(fun.hir_id) - .map(|user_substs| UserTypeAnnotation::TypeOf(adt_def.did, user_substs)); + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(fun.hir_id) + .map(|u_ty| *u_ty) + .map(|mut u_ty| { + if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut u_ty.value { + *did = adt_def.did; + } + u_ty + }); + debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); let field_refs = args.iter() .enumerate() @@ -464,11 +471,14 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::Adt(adt, substs) => { match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); + debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); ExprKind::Adt { adt_def: adt, variant_index: VariantIdx::new(0), substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), + user_ty, fields: field_refs(cx, fields), base: base.as_ref().map(|base| { FruInfo { @@ -487,11 +497,18 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, assert!(base.is_none()); let index = adt.variant_index_with_id(variant_id); + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id) + .map(|u_ty| *u_ty); + debug!( + "make_mirror_unadjusted: (variant) user_ty={:?}", + user_ty + ); ExprKind::Adt { adt_def: adt, variant_index: index, substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), + user_ty, fields: field_refs(cx, fields), base: None, } @@ -635,8 +652,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprKind::Cast(ref source, ref cast_ty) => { // Check for a user-given type annotation on this `cast` - let user_ty = cx.tables.user_provided_tys().get(cast_ty.hir_id) - .map(|&t| UserTypeAnnotation::Ty(t)); + let user_provided_types = cx.tables.user_provided_types(); + let user_ty = user_provided_types.get(cast_ty.hir_id); debug!( "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}", @@ -742,20 +759,20 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span: expr.span, kind: cast, }; + debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); ExprKind::ValueTypeAscription { source: cast_expr.to_ref(), - user_ty: Some(user_ty), + user_ty: Some(*user_ty), } } else { cast } } hir::ExprKind::Type(ref source, ref ty) => { - let user_provided_tys = cx.tables.user_provided_tys(); - let user_ty = user_provided_tys - .get(ty.hir_id) - .map(|&c_ty| UserTypeAnnotation::Ty(c_ty)); + let user_provided_types = cx.tables.user_provided_types(); + let user_ty = user_provided_types.get(ty.hir_id).map(|u_ty| *u_ty); + debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); if source.is_place_expr() { ExprKind::PlaceTypeAscription { source: source.to_ref(), @@ -792,8 +809,9 @@ fn user_substs_applied_to_def( cx: &mut Cx<'a, 'gcx, 'tcx>, hir_id: hir::HirId, def: &Def, -) -> Option<UserTypeAnnotation<'tcx>> { - match def { +) -> Option<ty::CanonicalUserTypeAnnotation<'tcx>> { + debug!("user_substs_applied_to_def: def={:?}", def); + let user_provided_type = match def { // A reference to something callable -- e.g., a fn, method, or // a tuple-struct or tuple-variant. This has the type of a // `Fn` but with the user-given substitutions. @@ -802,8 +820,7 @@ fn user_substs_applied_to_def( Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) | Def::Const(_) | - Def::AssociatedConst(_) => - Some(UserTypeAnnotation::TypeOf(def.def_id(), cx.tables().user_substs(hir_id)?)), + Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty), // A unit struct/variant which is used as a value (e.g., // `None`). This has the type of the enum/struct that defines @@ -819,7 +836,9 @@ fn user_substs_applied_to_def( _ => bug!("user_substs_applied_to_def: unexpected def {:?} at {:?}", def, hir_id) - } + }; + debug!("user_substs_applied_to_def: user_provided_type={:?}", user_provided_type); + user_provided_type } fn method_callee<'a, 'gcx, 'tcx>( @@ -839,6 +858,7 @@ fn method_callee<'a, 'gcx, 'tcx>( span_bug!(expr.span, "no type-dependent def for method callee") }); let user_ty = user_substs_applied_to_def(cx, expr.hir_id, def); + debug!("method_callee: user_ty={:?}", user_ty); (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty) } }; @@ -906,6 +926,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::VariantCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => { let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); + debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { literal: ty::Const::zero_sized( cx.tcx, @@ -918,6 +939,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => { let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); + debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: ty::Const::unevaluated( cx.tcx, @@ -931,6 +953,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::StructCtor(def_id, CtorKind::Const) | Def::VariantCtor(def_id, CtorKind::Const) => { + let user_provided_types = cx.tables.user_provided_types(); + let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); + debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); match cx.tables().node_id_to_type(expr.hir_id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. @@ -939,7 +964,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, adt_def, variant_index: adt_def.variant_index_with_id(def_id), substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def), + user_ty: user_provided_type, fields: vec![], base: None, } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index bcca501e600ac..d36a6eb58b85a 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -4,11 +4,12 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use rustc::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp}; +use rustc::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc::hir::def_id::DefId; +use rustc::infer::canonical::Canonical; use rustc::middle::region; use rustc::ty::subst::Substs; -use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; +use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, UserTypeAnnotation}; use rustc::ty::layout::VariantIdx; use rustc::hir; use syntax::ast; @@ -265,7 +266,7 @@ pub enum ExprKind<'tcx> { /// Optional user-given substs: for something like `let x = /// Bar::<T> { ... }`. - user_ty: Option<UserTypeAnnotation<'tcx>>, + user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>, fields: Vec<FieldExprRef<'tcx>>, base: Option<FruInfo<'tcx>> @@ -273,12 +274,12 @@ pub enum ExprKind<'tcx> { PlaceTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option<UserTypeAnnotation<'tcx>>, + user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>, }, ValueTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option<UserTypeAnnotation<'tcx>>, + user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>, }, Closure { closure_id: DefId, @@ -288,7 +289,7 @@ pub enum ExprKind<'tcx> { }, Literal { literal: &'tcx Const<'tcx>, - user_ty: Option<UserTypeAnnotation<'tcx>>, + user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>, }, InlineAsm { asm: &'tcx hir::InlineAsm, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 62ec52aac1346..fd3b07c0357b5 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,9 +12,10 @@ use hair::util::UserAnnotatedTyHelpers; use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; -use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; +use rustc::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift}; +use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; @@ -63,9 +64,15 @@ pub(crate) struct PatternTypeProjections<'tcx> { } impl<'tcx> PatternTypeProjections<'tcx> { - pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> { + pub(crate) fn user_ty( + self, + annotations: &mut CanonicalUserTypeAnnotations<'tcx>, + ) -> UserTypeProjections<'tcx> { UserTypeProjections::from_projections( - self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span))) + self.contents + .into_iter() + .map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(annotations, span), span)) + ) } pub(crate) fn none() -> Self { @@ -115,30 +122,33 @@ impl<'tcx> PatternTypeProjections<'tcx> { } #[derive(Clone, Debug)] -pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>); +pub struct PatternTypeProjection<'tcx> { + pub base: CanonicalUserTypeAnnotation<'tcx>, + pub projs: Vec<ProjectionElem<'tcx, (), ()>>, +} impl<'tcx> PatternTypeProjection<'tcx> { pub(crate) fn index(&self) -> Self { let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Index(())); + new.projs.push(ProjectionElem::Index(())); new } pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Subslice { from, to }); + new.projs.push(ProjectionElem::Subslice { from, to }); new } pub(crate) fn deref(&self) -> Self { let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Deref); + new.projs.push(ProjectionElem::Deref); new } pub(crate) fn leaf(&self, field: Field) -> Self { let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Field(field, ())); + new.projs.push(ProjectionElem::Field(field, ())); new } @@ -147,24 +157,29 @@ impl<'tcx> PatternTypeProjection<'tcx> { variant_index: VariantIdx, field: Field) -> Self { let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); - new.0.projs.push(ProjectionElem::Field(field, ())); + new.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); + new.projs.push(ProjectionElem::Field(field, ())); new } - pub(crate) fn from_canonical_ty(c_ty: ty::CanonicalTy<'tcx>) -> Self { - Self::from_user_type(UserTypeAnnotation::Ty(c_ty)) - } - - pub(crate) fn from_user_type(u_ty: UserTypeAnnotation<'tcx>) -> Self { - Self::from_user_type_proj(UserTypeProjection { base: u_ty, projs: vec![], }) + pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self { + Self { + base: user_annotation, + projs: Vec::new(), + } } - pub(crate) fn from_user_type_proj(u_ty: UserTypeProjection<'tcx>) -> Self { - PatternTypeProjection(u_ty) + pub(crate) fn user_ty( + self, + annotations: &mut CanonicalUserTypeAnnotations<'tcx>, + span: Span, + ) -> UserTypeProjection<'tcx> { + let annotation_index = annotations.push((span, self.base)); + UserTypeProjection { + base: annotation_index, + projs: self.projs + } } - - pub(crate) fn user_ty(self) -> UserTypeProjection<'tcx> { self.0 } } #[derive(Clone, Debug)] @@ -788,18 +803,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { - let subpattern = Pattern { - span, - ty, - kind: Box::new(kind), - }; - - debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span); - - let pat_ty = PatternTypeProjection::from_user_type(user_ty); + debug!("lower_variant_or_leaf: user_ty={:?} span={:?}", user_ty, span); kind = PatternKind::AscribeUserType { - subpattern, - user_ty: pat_ty, + subpattern: Pattern { + span, + ty, + kind: Box::new(kind), + }, + user_ty: PatternTypeProjection::from_user_type(user_ty), user_ty_span: span, }; } diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index 050fb8b846ee0..f0f8263b64de5 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -1,37 +1,31 @@ use rustc::hir; -use rustc::mir::UserTypeAnnotation; -use rustc::ty::{self, AdtDef, TyCtxt}; +use rustc::ty::{self, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotation}; crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>; fn tables(&self) -> &ty::TypeckTables<'tcx>; - fn user_substs_applied_to_adt( - &self, - hir_id: hir::HirId, - adt_def: &'tcx AdtDef, - ) -> Option<UserTypeAnnotation<'tcx>> { - let user_substs = self.tables().user_substs(hir_id)?; - Some(UserTypeAnnotation::TypeOf(adt_def.did, user_substs)) - } - /// Looks up the type associated with this hir-id and applies the /// user-given substitutions; the hir-id must map to a suitable /// type. fn user_substs_applied_to_ty_of_hir_id( &self, hir_id: hir::HirId, - ) -> Option<UserTypeAnnotation<'tcx>> { - let user_substs = self.tables().user_substs(hir_id)?; + ) -> Option<CanonicalUserTypeAnnotation<'tcx>> { + let user_provided_types = self.tables().user_provided_types(); + let mut user_ty = *user_provided_types.get(hir_id)?; + debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); match &self.tables().node_id_to_type(hir_id).sty { - ty::Adt(adt_def, _) => Some(UserTypeAnnotation::TypeOf(adt_def.did, user_substs)), - ty::FnDef(def_id, _) => Some(UserTypeAnnotation::TypeOf(*def_id, user_substs)), - sty => bug!( - "sty: {:?} should not have user-substs {:?} recorded ", - sty, - user_substs - ), + ty::Adt(adt_def, ..) => { + if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut user_ty.value { + *did = adt_def.did; + } + Some(user_ty) + } + ty::FnDef(..) => Some(user_ty), + sty => + bug!("sty: {:?} should not have user provided type {:?} recorded ", sty, user_ty), } } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1029611cecd56..4c123d4a44b05 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -207,6 +207,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::new(), None, local_decls_for_sig(&sig, span), + IndexVec::new(), sig.inputs().len(), vec![], span, @@ -376,6 +377,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { IndexVec::new(), None, self.local_decls, + IndexVec::new(), self.sig.inputs().len(), vec![], self.span, @@ -825,6 +827,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::new(), None, local_decls, + IndexVec::new(), sig.inputs().len(), vec![], span, @@ -903,6 +906,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, IndexVec::new(), None, local_decls, + IndexVec::new(), sig.inputs().len(), vec![], span, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7e6554ae3d478..1602fc35a2c95 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -400,6 +400,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, IndexVec::new(), None, initial_locals, + IndexVec::new(), 0, vec![], mir.span, diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index d38ce3478d93d..b9ac0394306be 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -14,7 +14,7 @@ use rustc::traits::{ Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt, }; use rustc::ty::query::Providers; -use rustc::ty::subst::{Kind, Subst, UserSelfTy, UserSubsts}; +use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy}; use rustc::ty::{ FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, }; @@ -44,28 +44,16 @@ fn type_op_ascribe_user_type<'tcx>( tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let ( - param_env, - AscribeUserType { - mir_ty, - variance, - def_id, - user_substs, - projs, - }, + param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs } ) = key.into_parts(); debug!( - "type_op_ascribe_user_type(\ - mir_ty={:?}, variance={:?}, def_id={:?}, user_substs={:?}, projs={:?}\ - )", - mir_ty, variance, def_id, user_substs, projs, + "type_op_user_type_relation: mir_ty={:?} variance={:?} def_id={:?} \ + user_substs={:?} projs={:?}", + mir_ty, variance, def_id, user_substs, projs ); - let mut cx = AscribeUserTypeCx { - infcx, - param_env, - fulfill_cx, - }; + let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; cx.relate_mir_and_user_ty(mir_ty, variance, def_id, user_substs, projs)?; Ok(()) @@ -130,10 +118,9 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { projs: &[ProjectionKind<'tcx>], ) -> Result<(), NoSolution> { let UserSubsts { - substs, user_self_ty, + substs, } = user_substs; - let tcx = self.tcx(); let ty = tcx.type_of(def_id); @@ -174,8 +161,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { if let Some(UserSelfTy { impl_def_id, self_ty, - }) = user_self_ty - { + }) = user_self_ty { let impl_self_ty = self.tcx().type_of(impl_def_id); let impl_self_ty = self.subst(impl_self_ty, &substs); let impl_self_ty = self.normalize(impl_self_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 39beb2832851b..acb873206d5ab 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,13 +102,14 @@ use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, RegionKind, Visibility, - ToPolyTraitRef, ToPredicate}; +use rustc::ty::{ + self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility, + ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation +}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; -use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, - UserSelfTy, UserSubsts}; +use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts}; use rustc::ty::util::{Representability, IntTypeExt, Discr}; use rustc::ty::layout::VariantIdx; use syntax_pos::{self, BytePos, Span, MultiSpan}; @@ -974,10 +975,12 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { o_ty }; - let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty); + let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation( + &UserTypeAnnotation::Ty(revealed_ty) + ); debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}", ty.hir_id, o_ty, revealed_ty, c_ty); - self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty); + self.fcx.tables.borrow_mut().user_provided_types_mut().insert(ty.hir_id, c_ty); Some(LocalTy { decl_ty: o_ty, revealed_ty }) }, @@ -2108,8 +2111,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tables.borrow_mut().field_indices_mut().insert(hir_id, index); } - // The NodeId and the ItemLocalId must identify the same item. We just pass - // both of them for consistency checking. pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { @@ -2138,23 +2139,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !method.substs.is_noop() { let method_generics = self.tcx.generics_of(method.def_id); if !method_generics.params.is_empty() { - let user_substs = self.infcx.probe(|_| { - let just_method_substs = Substs::for_item(self.tcx, method.def_id, |param, _| { - let i = param.index as usize; - if i < method_generics.parent_count { - self.infcx.var_for_def(DUMMY_SP, param) - } else { - method.substs[i] - } - }); - self.infcx.canonicalize_user_type_annotation(&UserSubsts { - substs: just_method_substs, + let user_type_annotation = self.infcx.probe(|_| { + let user_substs = UserSubsts { + substs: Substs::for_item(self.tcx, method.def_id, |param, _| { + let i = param.index as usize; + if i < method_generics.parent_count { + self.infcx.var_for_def(DUMMY_SP, param) + } else { + method.substs[i] + } + }), user_self_ty: None, // not relevant here - }) + }; + + self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf( + method.def_id, + user_substs, + )) }); - debug!("write_method_call: user_substs = {:?}", user_substs); - self.write_user_substs(hir_id, user_substs); + debug!("write_method_call: user_type_annotation={:?}", user_type_annotation); + self.write_user_type_annotation(hir_id, user_type_annotation); } } } @@ -2177,41 +2182,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// This should be invoked **before any unifications have /// occurred**, so that annotations like `Vec<_>` are preserved /// properly. - pub fn write_user_substs_from_substs( + pub fn write_user_type_annotation_from_substs( &self, hir_id: hir::HirId, + def_id: DefId, substs: &'tcx Substs<'tcx>, user_self_ty: Option<UserSelfTy<'tcx>>, ) { debug!( - "write_user_substs_from_substs({:?}, {:?}) in fcx {}", - hir_id, - substs, - self.tag(), + "write_user_type_annotation_from_substs: hir_id={:?} def_id={:?} substs={:?} \ + user_self_ty={:?} in fcx {}", + hir_id, def_id, substs, user_self_ty, self.tag(), ); if !substs.is_noop() { - let user_substs = self.infcx.canonicalize_user_type_annotation(&UserSubsts { - substs, - user_self_ty, - }); - debug!("instantiate_value_path: user_substs = {:?}", user_substs); - self.write_user_substs(hir_id, user_substs); + let canonicalized = self.infcx.canonicalize_user_type_annotation( + &UserTypeAnnotation::TypeOf(def_id, UserSubsts { + substs, + user_self_ty, + }) + ); + debug!("write_user_type_annotation_from_substs: canonicalized={:?}", canonicalized); + self.write_user_type_annotation(hir_id, canonicalized); } } - pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalUserSubsts<'tcx>) { + pub fn write_user_type_annotation( + &self, + hir_id: hir::HirId, + canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>, + ) { debug!( - "write_user_substs({:?}, {:?}) in fcx {}", - hir_id, - substs, - self.tag(), + "write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}", + hir_id, canonical_user_type_annotation, self.tag(), ); - if !substs.is_identity() { - self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs); + if !canonical_user_type_annotation.is_identity() { + self.tables.borrow_mut().user_provided_types_mut().insert( + hir_id, canonical_user_type_annotation + ); } else { - debug!("write_user_substs: skipping identity substs"); + debug!("write_user_type_annotation: skipping identity substs"); } } @@ -2386,8 +2397,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // although I have my doubts). Other sorts of things are // already sufficiently enforced with erased regions. =) if ty.has_free_regions() || ty.has_projections() { - let c_ty = self.infcx.canonicalize_response(&ty); - self.tables.borrow_mut().user_provided_tys_mut().insert(ast_ty.hir_id, c_ty); + let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty)); + self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); } ty @@ -3734,7 +3745,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((variant, did, substs)) = variant { debug!("check_struct_path: did={:?} substs={:?}", did, substs); let hir_id = self.tcx.hir().node_to_hir_id(node_id); - self.write_user_substs_from_substs(hir_id, substs, None); + self.write_user_type_annotation_from_substs(hir_id, did, substs, None); // Check bounds on type arguments used in the path. let bounds = self.instantiate_bounds(path_span, did, substs); @@ -5290,7 +5301,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // First, store the "user substs" for later. let hir_id = tcx.hir().node_to_hir_id(node_id); - self.write_user_substs_from_substs(hir_id, substs, user_self_ty); + self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty); // Add all the obligations that are required, substituting and // normalized appropriately. diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8bd9b097d2df1..53ea497f01add 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -357,7 +357,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); let common_local_id_root = fcx_tables.local_id_root.unwrap(); - for (&local_id, c_ty) in fcx_tables.user_provided_tys().iter() { + for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { let hir_id = hir::HirId { owner: common_local_id_root.index, local_id, @@ -374,8 +374,17 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }; self.tables - .user_provided_tys_mut() + .user_provided_types_mut() .insert(hir_id, c_ty.clone()); + + if let ty::UserTypeAnnotation::TypeOf(_, user_substs) = c_ty.value { + if self.rustc_dump_user_substs { + // This is a unit-testing mechanism. + let node_id = self.tcx().hir().hir_to_node_id(hir_id); + let span = self.tcx().hir().span(node_id); + self.tcx().sess.span_err(span, &format!("user substs: {:?}", user_substs)); + } + } } } @@ -573,22 +582,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { assert!(!substs.needs_infer() && !substs.has_placeholders()); self.tables.node_substs_mut().insert(hir_id, substs); } - - // Copy over any user-substs - if let Some(user_substs) = self.fcx.tables.borrow().user_substs(hir_id) { - let user_substs = self.tcx().lift_to_global(&user_substs).unwrap(); - self.tables.user_substs_mut().insert(hir_id, user_substs); - - // Unit-testing mechanism: - if self.rustc_dump_user_substs { - let node_id = self.tcx().hir().hir_to_node_id(hir_id); - let span = self.tcx().hir().span(node_id); - self.tcx().sess.span_err( - span, - &format!("user substs: {:?}", user_substs), - ); - } - } } fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index bb304ea12ca7f..88fd53d4ba59d 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -37,7 +37,7 @@ fn main() { // StorageLive(_4); // _4 = std::option::Option<std::boxed::Box<u32>>::None; // FakeRead(ForLet, _4); -// AscribeUserType(_4, o, UserTypeProjection { base: Ty(Canonical { max_universe: U0, variables: [], value: std::option::Option<std::boxed::Box<u32>> }), projs: [] }); +// AscribeUserType(_4, o, UserTypeProjection { base: UserTypeAnnotation(1), projs: [] }); // StorageLive(_5); // StorageLive(_6); // _6 = move _4; diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr index 5a359cf9ed8f1..123c26195d006 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -1,4 +1,4 @@ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [u32], user_self_ty: None } --> $DIR/dump-adt-brace-struct.rs:18:5 | LL | SomeStruct::<u32> { t: 22 }; //~ ERROR [u32] diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr index 3f159cc92b54f..fc4544437c5b1 100644 --- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr +++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr @@ -1,26 +1,26 @@ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } } - --> $DIR/dump-fn-method.rs:26:13 +error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:44:5 | -LL | let x = foo::<u32>; //~ ERROR [u32] - | ^^^^^^^^^^ +LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32] + | ^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } } +error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } --> $DIR/dump-fn-method.rs:32:13 | LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } --> $DIR/dump-fn-method.rs:36:13 | LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } - --> $DIR/dump-fn-method.rs:44:5 +error: user substs: UserSubsts { substs: [u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:26:13 | -LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = foo::<u32>; //~ ERROR [u32] + | ^^^^^^^^^^ error: aborting due to 4 previous errors From 43538cb8d4e25299afdbf68600ad0f824cdcb5e5 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Thu, 22 Nov 2018 20:35:24 +0100 Subject: [PATCH 058/124] Always check well-formedness. This commit uses the map introduced by the previous commit to ensure that types are always checked for well-formedness by the NLL type check. Previously, without the map introduced by the previous commit, types would not be checked for well-formedness if the `AscribeUserType` statement that would trigger that check was removed as unreachable code. --- src/librustc/dep_graph/dep_node.rs | 4 +- src/librustc/traits/query/mod.rs | 4 + .../traits/query/type_op/ascribe_user_type.rs | 60 +++++++++- src/librustc/ty/query/config.rs | 12 +- src/librustc/ty/query/mod.rs | 11 +- src/librustc/ty/query/plumbing.rs | 1 + .../borrow_check/nll/type_check/mod.rs | 24 ++++ src/librustc_traits/type_op.rs | 106 +++++++++++++----- ...ns-free-region-ordering-caller1.nll.stderr | 19 +++- ...egions-outlives-projection-container-wc.rs | 4 +- ...ns-outlives-projection-container-wc.stderr | 6 +- 11 files changed, 209 insertions(+), 42 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e5fd0aa3c9cbd..1f19e6fc689c1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -62,7 +62,8 @@ use syntax_pos::symbol::InternedString; use traits; use traits::query::{ CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, - CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal, + CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal, + CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, }; use ty::{TyCtxt, FnSig, Instance, InstanceDef, @@ -650,6 +651,7 @@ define_dep_nodes!( <'tcx> [] EvaluateObligation(CanonicalPredicateGoal<'tcx>), [] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>), [] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>), + [] TypeOpAscribeUserTypeWellFormed(CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>), [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>), [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>), [] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>), diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 59f786025b224..3203dc4e8cf82 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -28,6 +28,10 @@ pub type CanonicalPredicateGoal<'tcx> = pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>; +pub type CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> = + Canonical<'tcx, ty::ParamEnvAnd<'tcx, + type_op::ascribe_user_type::AscribeUserTypeWellFormed<'tcx>>>; + pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>; diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index 365c1d67ef97a..993d09d2ed02d 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -2,7 +2,7 @@ use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, Que use traits::query::Fallible; use hir::def_id::DefId; use mir::ProjectionKind; -use ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use ty::{self, ParamEnvAnd, Ty, TyCtxt, UserTypeAnnotation}; use ty::subst::UserSubsts; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] @@ -22,7 +22,7 @@ impl<'tcx> AscribeUserType<'tcx> { user_substs: UserSubsts<'tcx>, projs: &'tcx ty::List<ProjectionKind<'tcx>>, ) -> Self { - AscribeUserType { mir_ty, variance, def_id, user_substs, projs } + Self { mir_ty, variance, def_id, user_substs, projs } } } @@ -68,3 +68,59 @@ impl_stable_hash_for! { mir_ty, variance, def_id, user_substs, projs } } + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct AscribeUserTypeWellFormed<'tcx> { + pub user_type_annotation: UserTypeAnnotation<'tcx>, +} + +impl<'tcx> AscribeUserTypeWellFormed<'tcx> { + pub fn new( + user_type_annotation: UserTypeAnnotation<'tcx>, + ) -> Self { + Self { user_type_annotation, } + } +} + +impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserTypeWellFormed<'tcx> { + type QueryResponse = (); + + fn try_fast_path( + _tcx: TyCtxt<'_, 'gcx, 'tcx>, + _key: &ParamEnvAnd<'tcx, Self>, + ) -> Option<Self::QueryResponse> { + None + } + + fn perform_query( + tcx: TyCtxt<'_, 'gcx, 'tcx>, + canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>, + ) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> { + tcx.type_op_ascribe_user_type_well_formed(canonicalized) + } + + fn shrink_to_tcx_lifetime( + v: &'a CanonicalizedQueryResponse<'gcx, ()>, + ) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> { + v + } +} + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for AscribeUserTypeWellFormed<'tcx> { + user_type_annotation + } +} + +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for AscribeUserTypeWellFormed<'a> { + type Lifted = AscribeUserTypeWellFormed<'tcx>; + user_type_annotation + } +} + +impl_stable_hash_for! { + struct AscribeUserTypeWellFormed<'tcx> { + user_type_annotation + } +} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 3464464aa229c..bed4dfd97ca49 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -5,7 +5,8 @@ use mir::interpret::GlobalId; use traits; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, - CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, + CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpAscribeUserTypeWellFormedGoal, + CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, }; use ty::{self, ParamEnvAnd, Ty, TyCtxt}; @@ -124,6 +125,15 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type_well_formed<'tcx> { + fn describe( + _tcx: TyCtxt<'_, '_, '_>, + goal: CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>, + ) -> Cow<'static, str> { + format!("evaluating `type_op_ascribe_user_type_well_formed` `{:?}`", goal).into() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> { format!("evaluating `type_op_eq` `{:?}`", goal).into() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 22bd1cd90a754..c2f208308b2d1 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -26,7 +26,8 @@ use session::config::OutputFilenames; use traits::{self, Vtable}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, - CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, + CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, + CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution, }; @@ -609,6 +610,14 @@ define_queries! { <'tcx> NoSolution, >, + /// Do not call this query directly: part of the `Eq` type-op + [] fn type_op_ascribe_user_type_well_formed: TypeOpAscribeUserTypeWellFormed( + CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> + ) -> Result< + Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, + NoSolution, + >, + /// Do not call this query directly: part of the `Eq` type-op [] fn type_op_eq: TypeOpEq( CanonicalTypeOpEqGoal<'tcx> diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 6887f480f72e0..c4fa27a8a3d36 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1219,6 +1219,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::EvaluateObligation | DepKind::EvaluateGoal | DepKind::TypeOpAscribeUserType | + DepKind::TypeOpAscribeUserTypeWellFormed | DepKind::TypeOpEq | DepKind::TypeOpSubtype | DepKind::TypeOpProvePredicate | diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 8f8abe09810a2..51ade33f74cf0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -916,6 +916,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } + /// Check that user type annotations are well formed. + fn check_user_type_annotations_are_well_formed(&mut self) { + for index in self.mir.user_type_annotations.indices() { + let (span, _) = &self.mir.user_type_annotations[index]; + let type_annotation = self.instantiated_type_annotations[&index]; + if let Err(terr) = self.fully_perform_op( + Locations::All(*span), + ConstraintCategory::Assignment, + self.param_env.and(type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( + type_annotation, + )), + ) { + span_mirbug!( + self, + type_annotation, + "bad user type annotation: {:?}", + terr, + ); + } + } + } + /// Given some operation `op` that manipulates types, proves /// predicates, or otherwise uses the inference context, executes /// `op` and then executes all the further obligations that `op` @@ -2389,6 +2411,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.check_terminator(mir, block_data.terminator(), location); self.check_iscleanup(mir, block_data); } + + self.check_user_type_annotations_are_well_formed(); } fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index b9ac0394306be..6691a036ac28c 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -4,7 +4,7 @@ use rustc::infer::InferCtxt; use rustc::hir::def_id::DefId; use rustc::mir::ProjectionKind; use rustc::mir::tcx::PlaceTy; -use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType; +use rustc::traits::query::type_op::ascribe_user_type::{AscribeUserType, AscribeUserTypeWellFormed}; use rustc::traits::query::type_op::eq::Eq; use rustc::traits::query::type_op::normalize::Normalize; use rustc::traits::query::type_op::prove_predicate::ProvePredicate; @@ -17,6 +17,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy}; use rustc::ty::{ FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, + UserTypeAnnotation, }; use rustc_data_structures::sync::Lrc; use std::fmt; @@ -26,6 +27,7 @@ use syntax_pos::DUMMY_SP; crate fn provide(p: &mut Providers) { *p = Providers { type_op_ascribe_user_type, + type_op_ascribe_user_type_well_formed, type_op_eq, type_op_prove_predicate, type_op_subtype, @@ -48,7 +50,7 @@ fn type_op_ascribe_user_type<'tcx>( ) = key.into_parts(); debug!( - "type_op_user_type_relation: mir_ty={:?} variance={:?} def_id={:?} \ + "type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \ user_substs={:?} projs={:?}", mir_ty, variance, def_id, user_substs, projs ); @@ -60,6 +62,28 @@ fn type_op_ascribe_user_type<'tcx>( }) } +fn type_op_ascribe_user_type_well_formed<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserTypeWellFormed<'tcx>>>, +) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { + tcx.infer_ctxt() + .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { + let ( + param_env, AscribeUserTypeWellFormed { user_type_annotation } + ) = key.into_parts(); + + debug!( + "type_op_ascribe_user_type_well_formed: user_type_annotation={:?}", + user_type_annotation, + ); + + let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; + cx.well_formed(user_type_annotation)?; + + Ok(()) + }) +} + struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> { infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, param_env: ParamEnv<'tcx>, @@ -109,6 +133,56 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { value.subst(self.tcx(), substs) } + fn well_formed( + &mut self, + type_annotation: UserTypeAnnotation<'tcx> + ) -> Result<(), NoSolution> { + match type_annotation { + UserTypeAnnotation::Ty(ty) => { + self.prove_predicate(Predicate::WellFormed(ty)); + Ok(()) + }, + UserTypeAnnotation::TypeOf(did, user_substs) => { + let UserSubsts { + user_self_ty, + substs, + } = user_substs; + + let ty = self.tcx().type_of(did); + let ty = self.subst(ty, substs); + debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); + let ty = self.normalize(ty); + + if let Some(UserSelfTy { + impl_def_id, + self_ty, + }) = user_self_ty { + let impl_self_ty = self.tcx().type_of(impl_def_id); + let impl_self_ty = self.subst(impl_self_ty, &substs); + let impl_self_ty = self.normalize(impl_self_ty); + + self.relate(self_ty, Variance::Invariant, impl_self_ty)?; + + self.prove_predicate(Predicate::WellFormed(impl_self_ty)); + } + + // In addition to proving the predicates, we have to + // prove that `ty` is well-formed -- this is because + // the WF of `ty` is predicated on the substs being + // well-formed, and we haven't proven *that*. We don't + // want to prove the WF of types from `substs` directly because they + // haven't been normalized. + // + // FIXME(nmatsakis): Well, perhaps we should normalize + // them? This would only be relevant if some input + // type were ill-formed but did not appear in `ty`, + // which...could happen with normalization... + self.prove_predicate(Predicate::WellFormed(ty)); + Ok(()) + }, + } + } + fn relate_mir_and_user_ty( &mut self, mir_ty: Ty<'tcx>, @@ -118,7 +192,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { projs: &[ProjectionKind<'tcx>], ) -> Result<(), NoSolution> { let UserSubsts { - user_self_ty, + user_self_ty: _, substs, } = user_substs; let tcx = self.tcx(); @@ -158,19 +232,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.relate(mir_ty, variance, ty)?; } - if let Some(UserSelfTy { - impl_def_id, - self_ty, - }) = user_self_ty { - let impl_self_ty = self.tcx().type_of(impl_def_id); - let impl_self_ty = self.subst(impl_self_ty, &substs); - let impl_self_ty = self.normalize(impl_self_ty); - - self.relate(self_ty, Variance::Invariant, impl_self_ty)?; - - self.prove_predicate(Predicate::WellFormed(impl_self_ty)); - } - // Prove the predicates coming along with `def_id`. // // Also, normalize the `instantiated_predicates` @@ -184,19 +245,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.prove_predicate(instantiated_predicate); } - // In addition to proving the predicates, we have to - // prove that `ty` is well-formed -- this is because - // the WF of `ty` is predicated on the substs being - // well-formed, and we haven't proven *that*. We don't - // want to prove the WF of types from `substs` directly because they - // haven't been normalized. - // - // FIXME(nmatsakis): Well, perhaps we should normalize - // them? This would only be relevant if some input - // type were ill-formed but did not appear in `ty`, - // which...could happen with normalization... - self.prove_predicate(Predicate::WellFormed(ty)); - Ok(()) } } diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index 92c21fcb4aec5..abda7ec5e07a6 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -12,6 +12,21 @@ LL | let z: &'a & usize = &(&y); LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error[E0597]: `y` does not live long enough + --> $DIR/regions-free-region-ordering-caller1.rs:9:27 + | +LL | fn call1<'a>(x: &'a usize) { + | -- lifetime `'a` defined here +... +LL | let z: &'a & usize = &(&y); + | ----------- ^^^^ borrowed value does not live long enough + | | + | assignment requires that `y` is borrowed for `'a` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0716`. +Some errors occurred: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index d38706defe7ad..91a0d8590ff34 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -31,9 +31,7 @@ fn with_assoc<'a,'b>() { // outlive 'a. In this case, that means TheType<'b>::TheAssocType, // which is &'b (), must outlive 'a. - // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if - // `_x` is changed to `_` - let _x: &'a WithAssoc<TheType<'b>> = loop { }; + let _: &'a WithAssoc<TheType<'b>> = loop { }; //~^ ERROR reference has a longer lifetime } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr index 2ed9fd4f9b4cf..0d73d3d64322e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr @@ -1,8 +1,8 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-wc.rs:36:13 + --> $DIR/regions-outlives-projection-container-wc.rs:34:12 | -LL | let _x: &'a WithAssoc<TheType<'b>> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: &'a WithAssoc<TheType<'b>> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 --> $DIR/regions-outlives-projection-container-wc.rs:28:15 From 7fc1fee71f26b115ff33d265657531062b134bda Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Fri, 23 Nov 2018 11:55:09 +0100 Subject: [PATCH 059/124] Add test for unreachable well-formedness. This commit adds a test for checking that types are well-formed when unreachable. --- src/test/ui/issue-54943.rs | 7 +++++++ src/test/ui/issue-54943.stderr | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/issue-54943.rs create mode 100644 src/test/ui/issue-54943.stderr diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs new file mode 100644 index 0000000000000..c2214f57dafec --- /dev/null +++ b/src/test/ui/issue-54943.rs @@ -0,0 +1,7 @@ +fn foo<T: 'static>() { } + +fn main<'a>() { + return; + + let x = foo::<&'a u32>(); +} diff --git a/src/test/ui/issue-54943.stderr b/src/test/ui/issue-54943.stderr new file mode 100644 index 0000000000000..62aacee811110 --- /dev/null +++ b/src/test/ui/issue-54943.stderr @@ -0,0 +1,11 @@ +error[E0477]: the type `&'a u32` does not fulfill the required lifetime + --> $DIR/issue-54943.rs:6:13 + | +LL | let x = foo::<&'a u32>(); + | ^^^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. From 1681b2d33b249d598517f35d983e3dbd9921746b Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sat, 24 Nov 2018 12:56:24 +0100 Subject: [PATCH 060/124] Type annotations in associated constant patterns. This commit adds support for respecting user type annotations with associated constants in patterns. --- src/librustc_mir/hair/pattern/mod.rs | 26 +++++++++++++++++-- src/librustc_typeck/check/method/mod.rs | 22 +++++++++------- src/librustc_typeck/check/mod.rs | 2 ++ .../associated-const-range-match-patterns.rs | 2 +- src/test/ui/issue-55511.nll.stderr | 15 +++++++++++ src/test/ui/issue-55511.rs | 18 +++++++++++++ src/test/ui/issue-55511.stderr | 14 ++++++++++ 7 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/issue-55511.nll.stderr create mode 100644 src/test/ui/issue-55511.rs create mode 100644 src/test/ui/issue-55511.stderr diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index fd3b07c0357b5..00de40d8cff83 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -848,7 +848,28 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; match self.tcx.at(span).const_eval(self.param_env.and(cid)) { Ok(value) => { - return self.const_to_pat(instance, value, id, span) + let pattern = self.const_to_pat(instance, value, id, span); + if !is_associated_const { + return pattern; + } + + let user_provided_types = self.tables().user_provided_types(); + return if let Some(u_ty) = user_provided_types.get(id) { + let user_ty = PatternTypeProjection::from_user_type(*u_ty); + Pattern { + span, + kind: Box::new( + PatternKind::AscribeUserType { + subpattern: pattern, + user_ty, + user_ty_span: span, + } + ), + ty: value.ty, + } + } else { + pattern + } }, Err(_) => { self.tcx.sess.span_err( @@ -938,7 +959,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { id: hir::HirId, span: Span, ) -> Pattern<'tcx> { - debug!("const_to_pat: cv={:#?}", cv); + debug!("const_to_pat: cv={:#?} id={:?}", cv, id); let adt_subpattern = |i, variant_opt| { let field = Field::new(i); let val = const_field( @@ -956,6 +977,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } }).collect::<Vec<_>>() }; + debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span); let kind = match cv.ty.sty { ty::Float(_) => { let id = self.tcx.hir().hir_to_node_id(id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index fe5f43e3c01ef..1758f76252456 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -357,16 +357,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) } - pub fn resolve_ufcs(&self, - span: Span, - method_name: ast::Ident, - self_ty: Ty<'tcx>, - expr_id: ast::NodeId) - -> Result<Def, MethodError<'tcx>> { - debug!("resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", - method_name, - self_ty, - expr_id + pub fn resolve_ufcs( + &self, + span: Span, + method_name: ast::Ident, + self_ty: Ty<'tcx>, + expr_id: ast::NodeId + ) -> Result<Def, MethodError<'tcx>> { + debug!( + "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", + method_name, self_ty, expr_id, ); let tcx = self.tcx; @@ -375,6 +375,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match self.probe_for_name(span, mode, method_name, IsSuggestion(false), self_ty, expr_id, ProbeScope::TraitsInScope) { Ok(pick) => { + debug!("resolve_ufcs: pick={:?}", pick); if let Some(import_id) = pick.import_id { let import_def_id = tcx.hir().local_def_id(import_id); debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); @@ -383,6 +384,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let def = pick.item.def(); + debug!("resolve_ufcs: def={:?}", def); tcx.check_stability(def.def_id(), Some(expr_id), span); Ok(def) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index acb873206d5ab..ff4574eb283fd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4584,6 +4584,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) { + debug!("resolve_ty_and_def_ufcs: qpath={:?} node_id={:?} span={:?}", qpath, node_id, span); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { return (path.def, @@ -5104,6 +5105,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Method(def_id) | Def::AssociatedConst(def_id) => { let container = tcx.associated_item(def_id).container; + debug!("instantiate_value_path: def={:?} container={:?}", def, container); match container { ty::TraitContainer(trait_did) => { callee::check_legal_trait_for_method_call(tcx, span, trait_did) diff --git a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs index 647652d02734a..4801369cfd1a8 100644 --- a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs +++ b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(dead_code)] +#![allow(dead_code, unreachable_patterns)] struct Foo; diff --git a/src/test/ui/issue-55511.nll.stderr b/src/test/ui/issue-55511.nll.stderr new file mode 100644 index 0000000000000..97f8015dfc147 --- /dev/null +++ b/src/test/ui/issue-55511.nll.stderr @@ -0,0 +1,15 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-55511.rs:13:28 + | +LL | let b = Some(Cell::new(&a)); + | ^^ borrowed value does not live long enough +LL | match b { +LL | <() as Foo<'static>>::C => { } + | ----------------------- type annotation requires that `a` is borrowed for `'static` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-55511.rs b/src/test/ui/issue-55511.rs new file mode 100644 index 0000000000000..93bd78c44d946 --- /dev/null +++ b/src/test/ui/issue-55511.rs @@ -0,0 +1,18 @@ +use std::cell::Cell; + +trait Foo<'a> { + const C: Option<Cell<&'a u32>>; +} + +impl<'a, T> Foo<'a> for T { + const C: Option<Cell<&'a u32>> = None; +} + +fn main() { + let a = 22; + let b = Some(Cell::new(&a)); + match b { + <() as Foo<'static>>::C => { } + _ => { } + } +} diff --git a/src/test/ui/issue-55511.stderr b/src/test/ui/issue-55511.stderr new file mode 100644 index 0000000000000..24668f045517a --- /dev/null +++ b/src/test/ui/issue-55511.stderr @@ -0,0 +1,14 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-55511.rs:13:29 + | +LL | let b = Some(Cell::new(&a)); + | ^ borrowed value does not live long enough +... +LL | } + | - borrowed value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From 70ffd8d2ef774a9b6a7689c8e6463b1e790fc77d Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sun, 25 Nov 2018 13:31:34 +0100 Subject: [PATCH 061/124] Add user type annotations to MIR dump. This commit writes the user type annotations to the MIR dump so that they are visible again. --- src/librustc_mir/borrow_check/nll/mod.rs | 3 ++- src/librustc_mir/util/pretty.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index c5eabbbefa9a4..a092c3b8ecde2 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -230,13 +230,14 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( // Before the CFG, dump out the values for each region variable. PassWhere::BeforeCFG => { regioncx.dump_mir(out)?; + writeln!(out, "|")?; if let Some(closure_region_requirements) = closure_region_requirements { - writeln!(out, "|")?; writeln!(out, "| Free Region Constraints")?; for_each_region_constraint(closure_region_requirements, &mut |msg| { writeln!(out, "| {}", msg) })?; + writeln!(out, "|")?; } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 35b367855ad28..6353eab6f6553 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -142,6 +142,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( } writeln!(file, "")?; extra_data(PassWhere::BeforeCFG, &mut file)?; + write_user_type_annotations(mir, &mut file)?; write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?; extra_data(PassWhere::AfterCFG, &mut file)?; }; @@ -618,6 +619,19 @@ fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { Ok(()) } +fn write_user_type_annotations(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { + if !mir.user_type_annotations.is_empty() { + writeln!(w, "| User Type Annotations")?; + } + for (index, (span, annotation)) in mir.user_type_annotations.iter_enumerated() { + writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation, span)?; + } + if !mir.user_type_annotations.is_empty() { + writeln!(w, "|")?; + } + Ok(()) +} + pub fn dump_mir_def_ids(tcx: TyCtxt, single: Option<DefId>) -> Vec<DefId> { if let Some(i) = single { vec![i] From 5e75340dc0fdcf447b868c687b103919fcc5192d Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sun, 25 Nov 2018 15:14:39 +0100 Subject: [PATCH 062/124] Support user type annotations in `ref` bindings. This commit adds support for user type annotations in variables declared using `ref` bindings. When a variable declared using a `ref` binding, then the `LocalDecl` has the type `&T` where the `&` was introduced by the `ref` binding but the canonicalized type annotation has only a `T` since the reference is implicit with the `ref` binding. Therefore, to support type annotations, the canonicalized type annotation either needs wrapped in a reference, or the `LocalDecl` type must have a wrapped reference removed for comparison. It is easier to remove the outer reference from the `LocalDecl` for the purpose of comparison, so that is the approach this commit takes. --- .../borrow_check/nll/type_check/mod.rs | 14 +++++++++++++- src/librustc_mir/build/block.rs | 1 + src/librustc_mir/build/matches/mod.rs | 17 ++++------------- src/librustc_mir/hair/pattern/mod.rs | 7 +------ src/librustc_typeck/check/mod.rs | 2 ++ src/test/ui/nll/issue-55401.rs | 8 ++++++++ src/test/ui/nll/issue-55401.stderr | 11 +++++++++++ 7 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/nll/issue-55401.rs create mode 100644 src/test/ui/nll/issue-55401.stderr diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 51ade33f74cf0..2c49dbd969d59 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -307,8 +307,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_type(local_decl, local_decl.ty); for (user_ty, span) in local_decl.user_ty.projections_and_spans() { + let ty = if !local_decl.is_nonref_binding() { + // If we have a binding of the form `let ref x: T = ..` then remove the outermost + // reference so we can check the type annotation for the remaining type. + if let ty::Ref(_, rty, _) = local_decl.ty.sty { + rty + } else { + bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); + } + } else { + local_decl.ty + }; + if let Err(terr) = self.cx.relate_type_and_user_type( - local_decl.ty, + ty, ty::Variance::Invariant, user_ty, Locations::All(*span), diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ad4e5a50dcd14..41718cfc87012 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -141,6 +141,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { None, remainder_span, lint_level, slice::from_ref(&pattern), ArmHasGuard(false), None); + debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_bindings( &pattern, &PatternTypeProjections::none(), diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 92642dff3dc68..085c58ef5ff66 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -409,6 +409,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let mut scope = self.source_scope; let num_patterns = patterns.len(); + debug!("declare_bindings: patterns={:?}", patterns); self.visit_bindings( &patterns[0], &PatternTypeProjections::none(), @@ -499,6 +500,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { &PatternTypeProjections<'tcx>, ), ) { + debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty); match *pattern.kind { PatternKind::Binding { mutability, @@ -509,19 +511,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ref subpattern, .. } => { - let pattern_ref_binding; // sidestep temp lifetime limitations. - let binding_user_ty = match mode { - BindingMode::ByValue => { pattern_user_ty } - BindingMode::ByRef(..) => { - // If this is a `ref` binding (e.g., `let ref - // x: T = ..`), then the type of `x` is not - // `T` but rather `&T`. - pattern_ref_binding = pattern_user_ty.ref_binding(); - &pattern_ref_binding - } - }; - - f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty); + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty); if let Some(subpattern) = subpattern.as_ref() { self.visit_bindings(subpattern, pattern_user_ty, f); } @@ -565,6 +555,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field); + debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty); self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 00de40d8cff83..6d562c69b2dc5 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -79,11 +79,6 @@ impl<'tcx> PatternTypeProjections<'tcx> { PatternTypeProjections { contents: vec![] } } - pub(crate) fn ref_binding(&self) -> Self { - // FIXME(#55401): ignore for now - PatternTypeProjections { contents: vec![] } - } - fn map_projs(&self, mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>) -> Self @@ -803,7 +798,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { - debug!("lower_variant_or_leaf: user_ty={:?} span={:?}", user_ty, span); + debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span); kind = PatternKind::AscribeUserType { subpattern: Pattern { span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ff4574eb283fd..36de41ef8a170 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2388,6 +2388,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); + debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); // If the type given by the user has free regions, save it for // later, since NLL would like to enforce those. Also pass in @@ -2398,6 +2399,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // already sufficiently enforced with erased regions. =) if ty.has_free_regions() || ty.has_projections() { let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty)); + debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty); self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); } diff --git a/src/test/ui/nll/issue-55401.rs b/src/test/ui/nll/issue-55401.rs new file mode 100644 index 0000000000000..2fa234491087d --- /dev/null +++ b/src/test/ui/nll/issue-55401.rs @@ -0,0 +1,8 @@ +#![feature(nll)] + +fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + let (ref y, _z): (&'a u32, u32) = (&22, 44); + *y //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr new file mode 100644 index 0000000000000..9e50db7b6045d --- /dev/null +++ b/src/test/ui/nll/issue-55401.stderr @@ -0,0 +1,11 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-55401.rs:5:5 + | +LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); +LL | *y //~ ERROR + | ^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + From 3507013f6194c5a047e89cbd1de54bb64d97e01f Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sat, 8 Dec 2018 00:50:35 +0100 Subject: [PATCH 063/124] Add explicit error annotations to test. This commit adds explicit error annotations to tests after rebasing which is now required. --- src/test/ui/issue-54943.rs | 1 + src/test/ui/issue-55511.nll.stderr | 2 +- src/test/ui/issue-55511.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs index c2214f57dafec..d5d0ae1a5e295 100644 --- a/src/test/ui/issue-54943.rs +++ b/src/test/ui/issue-54943.rs @@ -4,4 +4,5 @@ fn main<'a>() { return; let x = foo::<&'a u32>(); + //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477] } diff --git a/src/test/ui/issue-55511.nll.stderr b/src/test/ui/issue-55511.nll.stderr index 97f8015dfc147..bf3e58e8cdb19 100644 --- a/src/test/ui/issue-55511.nll.stderr +++ b/src/test/ui/issue-55511.nll.stderr @@ -3,7 +3,7 @@ error[E0597]: `a` does not live long enough | LL | let b = Some(Cell::new(&a)); | ^^ borrowed value does not live long enough -LL | match b { +... LL | <() as Foo<'static>>::C => { } | ----------------------- type annotation requires that `a` is borrowed for `'static` ... diff --git a/src/test/ui/issue-55511.rs b/src/test/ui/issue-55511.rs index 93bd78c44d946..4b9475ba62718 100644 --- a/src/test/ui/issue-55511.rs +++ b/src/test/ui/issue-55511.rs @@ -11,6 +11,7 @@ impl<'a, T> Foo<'a> for T { fn main() { let a = 22; let b = Some(Cell::new(&a)); + //~^ ERROR `a` does not live long enough [E0597] match b { <() as Foo<'static>>::C => { } _ => { } From ae43eec4a7413b1f14b3959af66116a5f8c7c822 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sun, 9 Dec 2018 03:07:31 +0100 Subject: [PATCH 064/124] Fix unresolved inference variable ICE. This commit moves well-formedness check for the `UserTypeAnnotation::Ty(..)` case from always running to only when the code is reachable. This solves the ICE that resulted from `src/test/ui/issue-54943-1.rs` (a minimal repro of `dropck-eyepatch` run-pass tests that failed). The main well-formedness check that was intended to be run despite unreachable code still is, that being the `UserTypeAnnotation::TypeOf(..)` case. Before this PR, the other case wasn't being checked at all. It is possible to fix this ICE while still always checking well-formedness for the `UserTypeAnnotation::Ty(..)` case but that solution will ICE in unreachable code for that case, the diff for that change [can be found here](0). [0]: https://gist.github.com/davidtwco/f9751ffd9c0508f7251c0f17adc3af53 --- .../borrow_check/nll/type_check/mod.rs | 58 ++++++++++++++----- .../incremental/hashes/let_expressions.rs | 2 +- src/test/ui/issue-54943-1.rs | 15 +++++ src/test/ui/issue-54943-2.rs | 18 ++++++ ...ns-free-region-ordering-caller1.nll.stderr | 2 +- 5 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/issue-54943-1.rs create mode 100644 src/test/ui/issue-54943-2.rs diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 2c49dbd969d59..d0ca050f0dff7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -933,19 +933,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { for index in self.mir.user_type_annotations.indices() { let (span, _) = &self.mir.user_type_annotations[index]; let type_annotation = self.instantiated_type_annotations[&index]; - if let Err(terr) = self.fully_perform_op( - Locations::All(*span), - ConstraintCategory::Assignment, - self.param_env.and(type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( - type_annotation, - )), - ) { - span_mirbug!( - self, - type_annotation, - "bad user type annotation: {:?}", - terr, - ); + match type_annotation { + // We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will + // cause ICEs (see comment in `relate_type_and_user_type`). + UserTypeAnnotation::TypeOf(..) => { + if let Err(terr) = self.fully_perform_op( + Locations::All(*span), + ConstraintCategory::Assignment, + self.param_env.and( + type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( + type_annotation, + ) + ), + ) { + span_mirbug!( + self, + type_annotation, + "bad user type annotation: {:?}", + terr, + ); + } + }, + _ => {}, } } } @@ -1079,7 +1088,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - match self.instantiated_type_annotations[&user_ty.base] { + let type_annotation = self.instantiated_type_annotations[&user_ty.base]; + match type_annotation { UserTypeAnnotation::Ty(ty) => { // The `TypeRelating` code assumes that "unresolved inference // variables" appear in the "a" side, so flip `Contravariant` @@ -1117,7 +1127,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { if let Ok(projected_ty) = curr_projected_ty { let ty = projected_ty.to_ty(tcx); self.relate_types(ty, v1, a, locations, category)?; + + // We'll get an ICE if we check for well-formedness of a + // `UserTypeAnnotation::Ty` that hasn't had types related. + // + // Doing this without the types having been related will result in + // `probe_ty_var` failing in the canonicalizer - in practice, this + // results in three run-pass tests failing. You can work around that + // by keeping an vec of projections instead of annotations and performing + // the projections before storing into `instantiated_type_annotations` + // but that still fails in dead code. + self.fully_perform_op( + locations, + category, + self.param_env.and( + type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( + UserTypeAnnotation::Ty(ty), + ) + ), + )?; } + } UserTypeAnnotation::TypeOf(def_id, user_substs) => { let projs = self.infcx.tcx.intern_projs(&user_ty.projs); diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 3aa66527ca7e8..b6050f059c27b 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,TypeckTables,MirValidated")] + except="HirBody,TypeckTables,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; diff --git a/src/test/ui/issue-54943-1.rs b/src/test/ui/issue-54943-1.rs new file mode 100644 index 0000000000000..7750e34036192 --- /dev/null +++ b/src/test/ui/issue-54943-1.rs @@ -0,0 +1,15 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/issue-54943-2.rs b/src/test/ui/issue-54943-2.rs new file mode 100644 index 0000000000000..f829c38c35d23 --- /dev/null +++ b/src/test/ui/issue-54943-2.rs @@ -0,0 +1,18 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. In particular, this test is in unreachable +// code as the initial fix for this ICE only worked if the code was reachable. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + return; + + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index abda7ec5e07a6..539343a68294f 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -21,7 +21,7 @@ LL | fn call1<'a>(x: &'a usize) { LL | let z: &'a & usize = &(&y); | ----------- ^^^^ borrowed value does not live long enough | | - | assignment requires that `y` is borrowed for `'a` + | type annotation requires that `y` is borrowed for `'a` ... LL | } | - `y` dropped here while still borrowed From ac18fbb032ea4d21f7f8c4c3cd70193732cb1586 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Tue, 18 Dec 2018 21:27:22 +0100 Subject: [PATCH 065/124] Stop well-formedness checking unreachable code. This commit stops well-formedness checking applying to unreachable code and therefore stops some of the ICEs that the intended solution taken by this PR causes. By disabling these checks, we can land the other fixes and larger refactors that this PR includes. --- src/librustc/dep_graph/dep_node.rs | 4 +- src/librustc/traits/query/mod.rs | 4 - .../traits/query/type_op/ascribe_user_type.rs | 58 +--------- src/librustc/ty/query/config.rs | 12 +- src/librustc/ty/query/mod.rs | 11 +- src/librustc/ty/query/plumbing.rs | 1 - src/librustc/ty/wf.rs | 7 +- .../borrow_check/nll/type_check/mod.rs | 53 --------- src/librustc_traits/type_op.rs | 103 +++++------------- src/test/ui/issue-54943-3.rs | 21 ++++ src/test/ui/issue-54943.rs | 11 +- src/test/ui/issue-54943.stderr | 11 -- ...ns-free-region-ordering-caller1.nll.stderr | 19 +--- 13 files changed, 70 insertions(+), 245 deletions(-) create mode 100644 src/test/ui/issue-54943-3.rs delete mode 100644 src/test/ui/issue-54943.stderr diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1f19e6fc689c1..e5fd0aa3c9cbd 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -62,8 +62,7 @@ use syntax_pos::symbol::InternedString; use traits; use traits::query::{ CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, - CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal, - CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal, + CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, }; use ty::{TyCtxt, FnSig, Instance, InstanceDef, @@ -651,7 +650,6 @@ define_dep_nodes!( <'tcx> [] EvaluateObligation(CanonicalPredicateGoal<'tcx>), [] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>), [] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>), - [] TypeOpAscribeUserTypeWellFormed(CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>), [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>), [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>), [] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>), diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 3203dc4e8cf82..59f786025b224 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -28,10 +28,6 @@ pub type CanonicalPredicateGoal<'tcx> = pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>; -pub type CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> = - Canonical<'tcx, ty::ParamEnvAnd<'tcx, - type_op::ascribe_user_type::AscribeUserTypeWellFormed<'tcx>>>; - pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>; diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index 993d09d2ed02d..b2f30564de93a 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -2,7 +2,7 @@ use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, Que use traits::query::Fallible; use hir::def_id::DefId; use mir::ProjectionKind; -use ty::{self, ParamEnvAnd, Ty, TyCtxt, UserTypeAnnotation}; +use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::subst::UserSubsts; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] @@ -68,59 +68,3 @@ impl_stable_hash_for! { mir_ty, variance, def_id, user_substs, projs } } - -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub struct AscribeUserTypeWellFormed<'tcx> { - pub user_type_annotation: UserTypeAnnotation<'tcx>, -} - -impl<'tcx> AscribeUserTypeWellFormed<'tcx> { - pub fn new( - user_type_annotation: UserTypeAnnotation<'tcx>, - ) -> Self { - Self { user_type_annotation, } - } -} - -impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserTypeWellFormed<'tcx> { - type QueryResponse = (); - - fn try_fast_path( - _tcx: TyCtxt<'_, 'gcx, 'tcx>, - _key: &ParamEnvAnd<'tcx, Self>, - ) -> Option<Self::QueryResponse> { - None - } - - fn perform_query( - tcx: TyCtxt<'_, 'gcx, 'tcx>, - canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>, - ) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> { - tcx.type_op_ascribe_user_type_well_formed(canonicalized) - } - - fn shrink_to_tcx_lifetime( - v: &'a CanonicalizedQueryResponse<'gcx, ()>, - ) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> { - v - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for AscribeUserTypeWellFormed<'tcx> { - user_type_annotation - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for AscribeUserTypeWellFormed<'a> { - type Lifted = AscribeUserTypeWellFormed<'tcx>; - user_type_annotation - } -} - -impl_stable_hash_for! { - struct AscribeUserTypeWellFormed<'tcx> { - user_type_annotation - } -} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index bed4dfd97ca49..3464464aa229c 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -5,8 +5,7 @@ use mir::interpret::GlobalId; use traits; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, - CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpAscribeUserTypeWellFormedGoal, - CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, + CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, }; use ty::{self, ParamEnvAnd, Ty, TyCtxt}; @@ -125,15 +124,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type_well_formed<'tcx> { - fn describe( - _tcx: TyCtxt<'_, '_, '_>, - goal: CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>, - ) -> Cow<'static, str> { - format!("evaluating `type_op_ascribe_user_type_well_formed` `{:?}`", goal).into() - } -} - impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> { format!("evaluating `type_op_eq` `{:?}`", goal).into() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index c2f208308b2d1..842aea07614dd 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -27,8 +27,7 @@ use traits::{self, Vtable}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, - CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal, - CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, + CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution, }; use traits::query::method_autoderef::MethodAutoderefStepsResult; @@ -610,14 +609,6 @@ define_queries! { <'tcx> NoSolution, >, - /// Do not call this query directly: part of the `Eq` type-op - [] fn type_op_ascribe_user_type_well_formed: TypeOpAscribeUserTypeWellFormed( - CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> - ) -> Result< - Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, - NoSolution, - >, - /// Do not call this query directly: part of the `Eq` type-op [] fn type_op_eq: TypeOpEq( CanonicalTypeOpEqGoal<'tcx> diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index c4fa27a8a3d36..6887f480f72e0 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1219,7 +1219,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::EvaluateObligation | DepKind::EvaluateGoal | DepKind::TypeOpAscribeUserType | - DepKind::TypeOpAscribeUserTypeWellFormed | DepKind::TypeOpEq | DepKind::TypeOpSubtype | DepKind::TypeOpProvePredicate | diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index f4a998fb9905a..aacc63c47de61 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -289,6 +289,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.out.extend(obligations); } + ty::FnDef(did, substs) => { + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + ty::Ref(r, rty, _) => { // WfReference if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { @@ -349,7 +354,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnPtr(_) => { // let the loop iterate into the argument/return // types appearing in the fn signature } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index d0ca050f0dff7..796a2f79f7554 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -928,37 +928,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } - /// Check that user type annotations are well formed. - fn check_user_type_annotations_are_well_formed(&mut self) { - for index in self.mir.user_type_annotations.indices() { - let (span, _) = &self.mir.user_type_annotations[index]; - let type_annotation = self.instantiated_type_annotations[&index]; - match type_annotation { - // We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will - // cause ICEs (see comment in `relate_type_and_user_type`). - UserTypeAnnotation::TypeOf(..) => { - if let Err(terr) = self.fully_perform_op( - Locations::All(*span), - ConstraintCategory::Assignment, - self.param_env.and( - type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( - type_annotation, - ) - ), - ) { - span_mirbug!( - self, - type_annotation, - "bad user type annotation: {:?}", - terr, - ); - } - }, - _ => {}, - } - } - } - /// Given some operation `op` that manipulates types, proves /// predicates, or otherwise uses the inference context, executes /// `op` and then executes all the further obligations that `op` @@ -1127,27 +1096,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { if let Ok(projected_ty) = curr_projected_ty { let ty = projected_ty.to_ty(tcx); self.relate_types(ty, v1, a, locations, category)?; - - // We'll get an ICE if we check for well-formedness of a - // `UserTypeAnnotation::Ty` that hasn't had types related. - // - // Doing this without the types having been related will result in - // `probe_ty_var` failing in the canonicalizer - in practice, this - // results in three run-pass tests failing. You can work around that - // by keeping an vec of projections instead of annotations and performing - // the projections before storing into `instantiated_type_annotations` - // but that still fails in dead code. - self.fully_perform_op( - locations, - category, - self.param_env.and( - type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( - UserTypeAnnotation::Ty(ty), - ) - ), - )?; } - } UserTypeAnnotation::TypeOf(def_id, user_substs) => { let projs = self.infcx.tcx.intern_projs(&user_ty.projs); @@ -2453,8 +2402,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.check_terminator(mir, block_data.terminator(), location); self.check_iscleanup(mir, block_data); } - - self.check_user_type_annotations_are_well_formed(); } fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 6691a036ac28c..52fcb5b80f4ae 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -4,7 +4,7 @@ use rustc::infer::InferCtxt; use rustc::hir::def_id::DefId; use rustc::mir::ProjectionKind; use rustc::mir::tcx::PlaceTy; -use rustc::traits::query::type_op::ascribe_user_type::{AscribeUserType, AscribeUserTypeWellFormed}; +use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType; use rustc::traits::query::type_op::eq::Eq; use rustc::traits::query::type_op::normalize::Normalize; use rustc::traits::query::type_op::prove_predicate::ProvePredicate; @@ -17,7 +17,6 @@ use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy}; use rustc::ty::{ FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, - UserTypeAnnotation, }; use rustc_data_structures::sync::Lrc; use std::fmt; @@ -27,7 +26,6 @@ use syntax_pos::DUMMY_SP; crate fn provide(p: &mut Providers) { *p = Providers { type_op_ascribe_user_type, - type_op_ascribe_user_type_well_formed, type_op_eq, type_op_prove_predicate, type_op_subtype, @@ -62,28 +60,6 @@ fn type_op_ascribe_user_type<'tcx>( }) } -fn type_op_ascribe_user_type_well_formed<'tcx>( - tcx: TyCtxt<'_, 'tcx, 'tcx>, - canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserTypeWellFormed<'tcx>>>, -) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { - tcx.infer_ctxt() - .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { - let ( - param_env, AscribeUserTypeWellFormed { user_type_annotation } - ) = key.into_parts(); - - debug!( - "type_op_ascribe_user_type_well_formed: user_type_annotation={:?}", - user_type_annotation, - ); - - let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; - cx.well_formed(user_type_annotation)?; - - Ok(()) - }) -} - struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> { infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, param_env: ParamEnv<'tcx>, @@ -133,56 +109,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { value.subst(self.tcx(), substs) } - fn well_formed( - &mut self, - type_annotation: UserTypeAnnotation<'tcx> - ) -> Result<(), NoSolution> { - match type_annotation { - UserTypeAnnotation::Ty(ty) => { - self.prove_predicate(Predicate::WellFormed(ty)); - Ok(()) - }, - UserTypeAnnotation::TypeOf(did, user_substs) => { - let UserSubsts { - user_self_ty, - substs, - } = user_substs; - - let ty = self.tcx().type_of(did); - let ty = self.subst(ty, substs); - debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); - let ty = self.normalize(ty); - - if let Some(UserSelfTy { - impl_def_id, - self_ty, - }) = user_self_ty { - let impl_self_ty = self.tcx().type_of(impl_def_id); - let impl_self_ty = self.subst(impl_self_ty, &substs); - let impl_self_ty = self.normalize(impl_self_ty); - - self.relate(self_ty, Variance::Invariant, impl_self_ty)?; - - self.prove_predicate(Predicate::WellFormed(impl_self_ty)); - } - - // In addition to proving the predicates, we have to - // prove that `ty` is well-formed -- this is because - // the WF of `ty` is predicated on the substs being - // well-formed, and we haven't proven *that*. We don't - // want to prove the WF of types from `substs` directly because they - // haven't been normalized. - // - // FIXME(nmatsakis): Well, perhaps we should normalize - // them? This would only be relevant if some input - // type were ill-formed but did not appear in `ty`, - // which...could happen with normalization... - self.prove_predicate(Predicate::WellFormed(ty)); - Ok(()) - }, - } - } - fn relate_mir_and_user_ty( &mut self, mir_ty: Ty<'tcx>, @@ -192,7 +118,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { projs: &[ProjectionKind<'tcx>], ) -> Result<(), NoSolution> { let UserSubsts { - user_self_ty: _, + user_self_ty, substs, } = user_substs; let tcx = self.tcx(); @@ -245,6 +171,31 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.prove_predicate(instantiated_predicate); } + if let Some(UserSelfTy { + impl_def_id, + self_ty, + }) = user_self_ty { + let impl_self_ty = self.tcx().type_of(impl_def_id); + let impl_self_ty = self.subst(impl_self_ty, &substs); + let impl_self_ty = self.normalize(impl_self_ty); + + self.relate(self_ty, Variance::Invariant, impl_self_ty)?; + + self.prove_predicate(Predicate::WellFormed(impl_self_ty)); + } + + // In addition to proving the predicates, we have to + // prove that `ty` is well-formed -- this is because + // the WF of `ty` is predicated on the substs being + // well-formed, and we haven't proven *that*. We don't + // want to prove the WF of types from `substs` directly because they + // haven't been normalized. + // + // FIXME(nmatsakis): Well, perhaps we should normalize + // them? This would only be relevant if some input + // type were ill-formed but did not appear in `ty`, + // which...could happen with normalization... + self.prove_predicate(Predicate::WellFormed(ty)); Ok(()) } } diff --git a/src/test/ui/issue-54943-3.rs b/src/test/ui/issue-54943-3.rs new file mode 100644 index 0000000000000..185077bd684a8 --- /dev/null +++ b/src/test/ui/issue-54943-3.rs @@ -0,0 +1,21 @@ +// compile-pass +// FIXME(#54943) This test targets the scenario where proving the WF requirements requires +// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring +// out the value of that `_` requires type-checking the surrounding code, but that code is dead, +// so our NLL region checker doesn't have access to it. This test should actually fail to compile. + +#![feature(nll)] +#![allow(warnings)] + +use std::fmt::Debug; + +fn foo<T: 'static + Debug>(_: T) { } + +fn bar<'a>() { + return; + + let _x = foo::<Vec<_>>(Vec::<&'a u32>::new()); + //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477] +} + +fn main() {} diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs index d5d0ae1a5e295..c720f62797580 100644 --- a/src/test/ui/issue-54943.rs +++ b/src/test/ui/issue-54943.rs @@ -1,8 +1,17 @@ +// compile-pass +// FIXME(#54943) This test targets the scenario where proving the WF requirements of a user +// type annotation requires checking dead code. This test should actually fail to compile. + +#![feature(nll)] +#![allow(warnings)] + fn foo<T: 'static>() { } -fn main<'a>() { +fn boo<'a>() { return; let x = foo::<&'a u32>(); //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477] } + +fn main() {} diff --git a/src/test/ui/issue-54943.stderr b/src/test/ui/issue-54943.stderr deleted file mode 100644 index 62aacee811110..0000000000000 --- a/src/test/ui/issue-54943.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0477]: the type `&'a u32` does not fulfill the required lifetime - --> $DIR/issue-54943.rs:6:13 - | -LL | let x = foo::<&'a u32>(); - | ^^^^^^^^^^^^^^ - | - = note: type must satisfy the static lifetime - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index 539343a68294f..92c21fcb4aec5 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -12,21 +12,6 @@ LL | let z: &'a & usize = &(&y); LL | } | - temporary value is freed at the end of this statement -error[E0597]: `y` does not live long enough - --> $DIR/regions-free-region-ordering-caller1.rs:9:27 - | -LL | fn call1<'a>(x: &'a usize) { - | -- lifetime `'a` defined here -... -LL | let z: &'a & usize = &(&y); - | ----------- ^^^^ borrowed value does not live long enough - | | - | type annotation requires that `y` is borrowed for `'a` -... -LL | } - | - `y` dropped here while still borrowed - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0597, E0716. -For more information about an error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0716`. From ab2a7853bc4da8f8252a7be548b71d2f0fd99ed8 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Wed, 19 Dec 2018 16:47:06 +0100 Subject: [PATCH 066/124] Stop duplicating projections of type annotation. This commit changes how type annotations are handled in bindings during MIR building. Instead of building up a `PatternTypeProjections` with the `CanonicalUserTypeAnnotation` and projections, the `CanonicalUserTypeAnnotation` is stored in the `canonical_user_type_annotations` map at the start and the (equivalent) `UserTypeProjections` is built up with the new index and same projections. This has the effect of deduplicating type annotations as instead of type annotations being added to the `canonical_user_type_annotations` map multiple times at the end after being duplicated (which happens in building up `PatternTypeProjections`), it is instead added once. --- src/librustc/mir/mod.rs | 75 +++++++++++++++++++++ src/librustc_mir/build/block.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 37 +++++----- src/librustc_mir/hair/mod.rs | 2 +- src/librustc_mir/hair/pattern/mod.rs | 97 +-------------------------- 5 files changed, 99 insertions(+), 114 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ecbe14c093f40..2936405ebd0b7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2519,6 +2519,48 @@ impl<'tcx> UserTypeProjections<'tcx> { pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> { self.contents.iter().map(|&(ref user_type, _span)| user_type) } + + pub fn push_projection( + mut self, + user_ty: &UserTypeProjection<'tcx>, + span: Span, + ) -> Self { + self.contents.push((user_ty.clone(), span)); + self + } + + fn map_projections( + mut self, + mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx> + ) -> Self { + self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect(); + self + } + + pub fn index(self) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.index()) + } + + pub fn subslice(self, from: u32, to: u32) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to)) + } + + pub fn deref(self) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.deref()) + } + + pub fn leaf(self, field: Field) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field)) + } + + pub fn variant( + self, + adt_def: &'tcx AdtDef, + variant_index: VariantIdx, + field: Field, + ) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) + } } /// Encodes the effect of a user-supplied type annotation on the @@ -2544,6 +2586,39 @@ pub struct UserTypeProjection<'tcx> { impl<'tcx> Copy for ProjectionKind<'tcx> { } +impl<'tcx> UserTypeProjection<'tcx> { + pub(crate) fn index(mut self) -> Self { + self.projs.push(ProjectionElem::Index(())); + self + } + + pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self { + self.projs.push(ProjectionElem::Subslice { from, to }); + self + } + + pub(crate) fn deref(mut self) -> Self { + self.projs.push(ProjectionElem::Deref); + self + } + + pub(crate) fn leaf(mut self, field: Field) -> Self { + self.projs.push(ProjectionElem::Field(field, ())); + self + } + + pub(crate) fn variant( + mut self, + adt_def: &'tcx AdtDef, + variant_index: VariantIdx, + field: Field, + ) -> Self { + self.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); + self.projs.push(ProjectionElem::Field(field, ())); + self + } +} + CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 41718cfc87012..f3d89a7a02515 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -144,7 +144,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_bindings( &pattern, - &PatternTypeProjections::none(), + UserTypeProjections::none(), &mut |this, _, _, _, node, span, _, _| { this.storage_live_binding(block, node, span, OutsideGuard); this.schedule_drop_for_binding(node, span, OutsideGuard); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 085c58ef5ff66..fe5bc6e19db65 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -8,7 +8,6 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard}; use build::{BlockAnd, BlockAndExtension, Builder}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use hair::*; -use hair::pattern::PatternTypeProjections; use rustc::mir::*; use rustc::ty::{self, Ty}; use rustc::ty::layout::VariantIdx; @@ -412,7 +411,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("declare_bindings: patterns={:?}", patterns); self.visit_bindings( &patterns[0], - &PatternTypeProjections::none(), + UserTypeProjections::none(), &mut |this, mutability, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { visibility_scope = @@ -488,7 +487,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub(super) fn visit_bindings( &mut self, pattern: &Pattern<'tcx>, - pattern_user_ty: &PatternTypeProjections<'tcx>, + pattern_user_ty: UserTypeProjections<'tcx>, f: &mut impl FnMut( &mut Self, Mutability, @@ -497,7 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { NodeId, Span, Ty<'tcx>, - &PatternTypeProjections<'tcx>, + UserTypeProjections<'tcx>, ), ) { debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty); @@ -511,7 +510,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ref subpattern, .. } => { - f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty); + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); if let Some(subpattern) = subpattern.as_ref() { self.visit_bindings(subpattern, pattern_user_ty, f); } @@ -529,18 +528,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let from = u32::try_from(prefix.len()).unwrap(); let to = u32::try_from(suffix.len()).unwrap(); for subpattern in prefix { - self.visit_bindings(subpattern, &pattern_user_ty.index(), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); } for subpattern in slice { - self.visit_bindings(subpattern, &pattern_user_ty.subslice(from, to), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f); } for subpattern in suffix { - self.visit_bindings(subpattern, &pattern_user_ty.index(), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); } } PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {} PatternKind::Deref { ref subpattern } => { - self.visit_bindings(subpattern, &pattern_user_ty.deref(), f); + self.visit_bindings(subpattern, pattern_user_ty.deref(), f); } PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { // This corresponds to something like @@ -548,23 +547,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // ``` // let A::<'a>(_): A<'static> = ...; // ``` - let subpattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span); - self.visit_bindings(subpattern, &subpattern_user_ty, f) + let annotation = (user_ty_span, user_ty.base); + let projection = UserTypeProjection { + base: self.canonical_user_type_annotations.push(annotation), + projs: user_ty.projs.clone(), + }; + let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span); + self.visit_bindings(subpattern, subpattern_user_ty, f) } PatternKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field); + let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty); - self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); + self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } PatternKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = pattern_user_ty.variant( + let subpattern_user_ty = pattern_user_ty.clone().variant( adt_def, variant_index, subpattern.field); - self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); + self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } } @@ -1465,7 +1469,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { num_patterns: usize, var_id: NodeId, var_ty: Ty<'tcx>, - user_var_ty: &PatternTypeProjections<'tcx>, + user_ty: UserTypeProjections<'tcx>, has_guard: ArmHasGuard, opt_match_place: Option<(Option<Place<'tcx>>, Span)>, pat_span: Span, @@ -1481,7 +1485,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()), BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()), }; - let user_ty = user_var_ty.clone().user_ty(&mut self.canonical_user_type_annotations); debug!("declare_binding: user_ty={:?}", user_ty); let local = LocalDecl::<'tcx> { mutability, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index d36a6eb58b85a..b56e3d4e77395 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -21,7 +21,7 @@ mod constant; pub mod pattern; pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern}; -pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections}; +pub(crate) use self::pattern::PatternTypeProjection; mod util; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 6d562c69b2dc5..10d2d7bc1b18b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,7 +12,7 @@ use hair::util::UserAnnotatedTyHelpers; use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; -use rustc::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections}; +use rustc::mir::{ProjectionElem, UserTypeProjection}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift}; use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation}; @@ -58,64 +58,6 @@ pub struct Pattern<'tcx> { } -#[derive(Clone, Debug)] -pub(crate) struct PatternTypeProjections<'tcx> { - contents: Vec<(PatternTypeProjection<'tcx>, Span)>, -} - -impl<'tcx> PatternTypeProjections<'tcx> { - pub(crate) fn user_ty( - self, - annotations: &mut CanonicalUserTypeAnnotations<'tcx>, - ) -> UserTypeProjections<'tcx> { - UserTypeProjections::from_projections( - self.contents - .into_iter() - .map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(annotations, span), span)) - ) - } - - pub(crate) fn none() -> Self { - PatternTypeProjections { contents: vec![] } - } - - fn map_projs(&self, - mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>) - -> Self - { - PatternTypeProjections { - contents: self.contents - .iter() - .map(|(proj, span)| (f(proj), *span)) - .collect(), } - } - - pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) } - - pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to)) - } - - pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) } - - pub(crate) fn leaf(&self, field: Field) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field)) - } - - pub(crate) fn variant(&self, - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - field: Field) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) - } - - pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self { - let mut new = self.clone(); - new.contents.push((user_ty.clone(), sp)); - new - } -} - #[derive(Clone, Debug)] pub struct PatternTypeProjection<'tcx> { pub base: CanonicalUserTypeAnnotation<'tcx>, @@ -123,40 +65,6 @@ pub struct PatternTypeProjection<'tcx> { } impl<'tcx> PatternTypeProjection<'tcx> { - pub(crate) fn index(&self) -> Self { - let mut new = self.clone(); - new.projs.push(ProjectionElem::Index(())); - new - } - - pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { - let mut new = self.clone(); - new.projs.push(ProjectionElem::Subslice { from, to }); - new - } - - pub(crate) fn deref(&self) -> Self { - let mut new = self.clone(); - new.projs.push(ProjectionElem::Deref); - new - } - - pub(crate) fn leaf(&self, field: Field) -> Self { - let mut new = self.clone(); - new.projs.push(ProjectionElem::Field(field, ())); - new - } - - pub(crate) fn variant(&self, - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - field: Field) -> Self { - let mut new = self.clone(); - new.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); - new.projs.push(ProjectionElem::Field(field, ())); - new - } - pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self { Self { base: user_annotation, @@ -169,9 +77,8 @@ impl<'tcx> PatternTypeProjection<'tcx> { annotations: &mut CanonicalUserTypeAnnotations<'tcx>, span: Span, ) -> UserTypeProjection<'tcx> { - let annotation_index = annotations.push((span, self.base)); UserTypeProjection { - base: annotation_index, + base: annotations.push((span, self.base)), projs: self.projs } } From 5d760c0b44fb41e01fcdd4ea2192968fb29dee63 Mon Sep 17 00:00:00 2001 From: David Wood <david@davidtw.co> Date: Sat, 22 Dec 2018 15:32:44 +0100 Subject: [PATCH 067/124] Guarantee `rustc_dump_user_substs` error order. This commit buffers the errors output by the `rustc_dump_user_substs` attribute so that they can be output in order of span and would therefore be consistent. --- src/librustc_typeck/check/writeback.rs | 17 ++++++++++++++++- .../nll/user-annotations/dump-fn-method.stderr | 16 ++++++++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 53ea497f01add..38de936a027ff 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -3,6 +3,7 @@ // substitutions. use check::FnCtxt; +use errors::DiagnosticBuilder; use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -357,6 +358,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); let common_local_id_root = fcx_tables.local_id_root.unwrap(); + let mut errors_buffer = Vec::new(); for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { let hir_id = hir::HirId { owner: common_local_id_root.index, @@ -382,10 +384,23 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // This is a unit-testing mechanism. let node_id = self.tcx().hir().hir_to_node_id(hir_id); let span = self.tcx().hir().span(node_id); - self.tcx().sess.span_err(span, &format!("user substs: {:?}", user_substs)); + // We need to buffer the errors in order to guarantee a consistent + // order when emitting them. + let err = self.tcx().sess.struct_span_err( + span, + &format!("user substs: {:?}", user_substs) + ); + err.buffer(&mut errors_buffer); } } } + + if !errors_buffer.is_empty() { + errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + for diag in errors_buffer.drain(..) { + DiagnosticBuilder::new_diagnostic(self.tcx().sess.diagnostic(), diag).emit(); + } + } } fn visit_user_provided_sigs(&mut self) { diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr index fc4544437c5b1..a1a4e43e8a3e9 100644 --- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr +++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr @@ -1,8 +1,8 @@ -error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } - --> $DIR/dump-fn-method.rs:44:5 +error: user substs: UserSubsts { substs: [u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:26:13 | -LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = foo::<u32>; //~ ERROR [u32] + | ^^^^^^^^^^ error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } --> $DIR/dump-fn-method.rs:32:13 @@ -16,11 +16,11 @@ error: user substs: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: UserSubsts { substs: [u32], user_self_ty: None } - --> $DIR/dump-fn-method.rs:26:13 +error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:44:5 | -LL | let x = foo::<u32>; //~ ERROR [u32] - | ^^^^^^^^^^ +LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors From 2a7cc8e308804650c90c89e1bce53f6812d18059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de> Date: Sun, 30 Dec 2018 18:16:09 +0100 Subject: [PATCH 068/124] submodules: update clippy from f7bdf500 to 39bd8449 Changes: ```` UI test cleanup: Extract iter_skip_next from methods.rs Update test output after rebase Remove false negatives from known problems Implement use_self for tuple structs Document known problems rustup https://github.com/rust-lang/rust/pull/56225/ Remove unnecessary `use` statements after `cargo fix` Apply cargo fix --edition-idioms fixes Use match ergonomics for booleans lint Use match ergonomics for block_in_if_condition lint Use match ergonomics for bit_mask lint Use match ergonomics for attrs lint Use match ergonomics for assign_ops lint Use match ergonomics for artithmetic lint Use match ergonomics for approx_const lint Remove crate:: prefixes from crate paths Support array indexing expressions in unused write to a constant Mark writes to constants as side-effect-less Update README local run command to remove syspath Remove unsafe from consts clippy lints Fix formatting Merge new_without_default_derive into new_without_default Only print out question_mark lint when it actually triggered Add failing test Reinserted commata Recomend `.as_ref()?` in certain situations Deduplicate some code? ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index f7bdf500d9389..39bd84494f4a9 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit f7bdf500d93895b6c02f8ae6a73002207f85e523 +Subproject commit 39bd84494f4a9b40f2e3b38416a91d52d5c4738b From 001294121395238afa32b8f2a83f899e085164e4 Mon Sep 17 00:00:00 2001 From: Jun Wu <quark@fb.com> Date: Sun, 30 Dec 2018 11:59:03 -0800 Subject: [PATCH 069/124] Add `-Z instrument-mcount` This flag inserts `mcount` function call to the beginning of every function after inline processing. So tracing tools like uftrace [1] (or ftrace for Linux kernel modules) have a chance to examine function calls. It is similar to the `-pg` flag provided by gcc or clang, but without generating a `__gmon_start__` function for executables. If a program runs without being traced, no `gmon.out` will be written to disk. Under the hood, it simply adds `"instrument-function-entry-inlined"="mcount"` attribute to every function. The `post-inline-ee-instrument` LLVM pass does the actual job. [1]: https://github.com/namhyung/uftrace --- src/librustc/session/config.rs | 2 ++ src/librustc/session/mod.rs | 9 ++++++++- src/librustc_codegen_llvm/attributes.rs | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e58c9d75a9db2..33409f9b4a74f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1227,6 +1227,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "verify incr. comp. hashes of green query instances"), incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], "ignore spans during ICH computation -- used for testing"), + instrument_mcount: bool = (false, parse_bool, [TRACKED], + "insert function instrument code for mcount-based tracing"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 4fc9b87ceef20..5c977d5969e16 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -503,6 +503,9 @@ impl Session { pub fn profile_queries_and_keys(&self) -> bool { self.opts.debugging_opts.profile_queries_and_keys } + pub fn instrument_mcount(&self) -> bool { + self.opts.debugging_opts.instrument_mcount + } pub fn count_llvm_insns(&self) -> bool { self.opts.debugging_opts.count_llvm_insns } @@ -667,7 +670,11 @@ impl Session { } pub fn must_not_eliminate_frame_pointers(&self) -> bool { - if let Some(x) = self.opts.cg.force_frame_pointers { + // "mcount" function relies on stack pointer. + // See https://sourceware.org/binutils/docs/gprof/Implementation.html + if self.instrument_mcount() { + true + } else if let Some(x) = self.opts.cg.force_frame_pointers { x } else { !self.target.target.options.eliminate_frame_pointer diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index acd1c4afd2e63..226b03c99c043 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -78,6 +78,18 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) } } +/// Tell LLVM what instrument function to insert. +#[inline] +pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + if cx.sess().instrument_mcount() { + // Similar to `clang -pg` behavior. Handled by the + // `post-inline-ee-instrument` LLVM pass. + llvm::AddFunctionAttrStringValue( + llfn, llvm::AttributePlace::Function, + const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount")); + } +} + pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes @@ -174,6 +186,7 @@ pub fn from_fn_attrs( } set_frame_pointer_elimination(cx, llfn); + set_instrument_function(cx, llfn); set_probestack(cx, llfn); if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { From 5345ae932a0a833c570541cfe3d7048c67e0c9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Sun, 30 Dec 2018 12:19:16 -0800 Subject: [PATCH 070/124] Address review comments: Remove new `PathResult` variant --- src/librustc_resolve/lib.rs | 9 +++------ src/librustc_resolve/macros.rs | 6 ++---- src/librustc_resolve/resolve_imports.rs | 6 +----- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3d81c75f1fd5e..cf949b62a634e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1034,8 +1034,6 @@ enum PathResult<'a> { NonModule(PathResolution), Indeterminate, Failed(Span, String, bool /* is the error from the last segment? */), - /// Encountered an error that is reported elsewhere - Ignore, } enum ModuleKind { @@ -1761,7 +1759,6 @@ impl<'a> Resolver<'a> { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); Def::Err } - PathResult::Ignore => Def::Err, }; let segments: Vec<_> = segments.iter().map(|seg| { @@ -3687,7 +3684,7 @@ impl<'a> Resolver<'a> { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } - PathResult::Module(..) | PathResult::Failed(..) | PathResult::Ignore => return None, + PathResult::Module(..) | PathResult::Failed(..) => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; @@ -3919,11 +3916,11 @@ impl<'a> Resolver<'a> { }); if let Some(candidate) = candidates.get(0) { format!("did you mean `{}`?", candidate.path) - } else if !ident.is_used_keyword() { + } else if !ident.is_reserved() { format!("maybe a missing `extern crate {};`?", ident) } else { // the parser will already have complained about the keyword being used - return PathResult::Ignore; + return PathResult::NonModule(err_path_resolution()); } } else if i == 0 { format!("use of undeclared type or module `{}`", ident) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6cb1be4a3064f..e5e6c7a994b7a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -365,8 +365,7 @@ impl<'a> Resolver<'a> { Ok(path_res.base_def()) } PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - PathResult::NonModule(..) | PathResult::Indeterminate | - PathResult::Failed(..) | PathResult::Ignore => { + PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => { Err(Determinacy::Determined) } PathResult::Module(..) => unreachable!(), @@ -931,8 +930,7 @@ impl<'a> Resolver<'a> { let def = path_res.base_def(); check_consistency(self, &path, path_span, kind, initial_def, def); } - path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) | - path_res @ PathResult::Ignore => { + path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => { let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res { (span, msg) } else { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 5da88a5c2fe8f..c84dbd2974624 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -774,8 +774,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { match path_res { PathResult::Module(module) => module, PathResult::Indeterminate => return false, - PathResult::NonModule(..) | PathResult::Failed(..) | - PathResult::Ignore => return true, + PathResult::NonModule(..) | PathResult::Failed(..) => return true, } }; @@ -869,9 +868,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { module } - PathResult::Ignore => { - return None; - } PathResult::Failed(span, msg, false) => { if no_ambiguity { assert!(directive.imported_module.get().is_none()); From 9f0925d61bf848cf58edcf4efd0520b90281af00 Mon Sep 17 00:00:00 2001 From: varkor <github@varkor.com> Date: Sun, 30 Dec 2018 09:56:59 +0000 Subject: [PATCH 071/124] Fix variable string size problem in transmute test --- src/test/ui/transmute/main.rs | 4 ++-- src/test/ui/transmute/main.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index dbad10c1c1980..ea233a47a78c1 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -1,5 +1,5 @@ -// normalize-stderr-32bit: "&str \(64 bits\)" -> "&str ($$STR bits)" -// normalize-stderr-64bit: "&str \(128 bits\)" -> "&str ($$STR bits)" +// normalize-stderr-32bit: "`&str` \(64 bits\)" -> "`&str` ($$STR bits)" +// normalize-stderr-64bit: "`&str` \(128 bits\)" -> "`&str` ($$STR bits)" diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index a152268c6d8f0..f4e88fc860acd 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -22,7 +22,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: `&str` (128 bits) + = note: source type: `&str` ($STR bits) = note: target type: `u8` (8 bits) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types From 1ea7f963ff5d885e5dd3194686cb1430cc11ff4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Sat, 22 Dec 2018 12:40:23 +0100 Subject: [PATCH 072/124] Group dep node data into a single structure --- src/librustc/dep_graph/dep_node.rs | 11 -- src/librustc/dep_graph/graph.rs | 195 ++++++++++++----------------- src/librustc/hir/map/collector.rs | 129 ++++++++++++------- 3 files changed, 165 insertions(+), 170 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e5fd0aa3c9cbd..070551c0b7b0a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -423,17 +423,6 @@ impl DefId { } } -impl DepKind { - #[inline] - pub fn fingerprint_needed_for_crate_hash(self) -> bool { - match self { - DepKind::HirBody | - DepKind::Krate => true, - _ => false, - } - } -} - define_dep_nodes!( <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 18c3e600778a3..8423c90447a25 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -21,12 +21,6 @@ use super::prev::PreviousDepGraph; #[derive(Clone)] pub struct DepGraph { data: Option<Lrc<DepGraphData>>, - - // A vector mapping depnodes from the current graph to their associated - // result value fingerprints. Do not rely on the length of this vector - // being the same as the number of nodes in the graph. The vector can - // contain an arbitrary number of zero-entries at the end. - fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>> } newtype_index! { @@ -81,30 +75,23 @@ impl DepGraph { pub fn new(prev_graph: PreviousDepGraph, prev_work_products: FxHashMap<WorkProductId, WorkProduct>) -> DepGraph { - // Pre-allocate the fingerprints array. We over-allocate a little so - // that we hopefully don't have to re-allocate during this compilation - // session. let prev_graph_node_count = prev_graph.node_count(); - let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, - (prev_graph_node_count * 115) / 100); DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: Lock::new(CurrentDepGraph::new()), + current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)), previous: prev_graph, colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)), loaded_from_cache: Default::default(), })), - fingerprints: Lrc::new(Lock::new(fingerprints)), } } pub fn new_disabled() -> DepGraph { DepGraph { data: None, - fingerprints: Lrc::new(Lock::new(IndexVec::new())), } } @@ -116,12 +103,12 @@ impl DepGraph { pub fn query(&self) -> DepGraphQuery { let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - let nodes: Vec<_> = current_dep_graph.nodes.iter().cloned().collect(); + let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect(); let mut edges = Vec::new(); - for (index, edge_targets) in current_dep_graph.edges.iter_enumerated() { - let from = current_dep_graph.nodes[index]; + for (from, edge_targets) in current_dep_graph.data.iter() + .map(|d| (d.node, &d.edges)) { for &edge_target in edge_targets.iter() { - let to = current_dep_graph.nodes[edge_target]; + let to = current_dep_graph.data[edge_target].node; edges.push((from, to)); } } @@ -201,7 +188,7 @@ impl DepGraph { reads: SmallVec::new(), read_set: Default::default(), })), - |data, key, task| data.borrow_mut().complete_task(key, task)) + |data, key, f, task| data.borrow_mut().complete_task(key, task, f)) } /// Creates a new dep-graph input with value `input` @@ -219,7 +206,7 @@ impl DepGraph { self.with_task_impl(key, cx, input, true, identity_fn, |_| OpenTask::Ignore, - |data, key, _| data.borrow_mut().alloc_node(key, SmallVec::new())) + |data, key, f, _| data.borrow_mut().alloc_node(key, SmallVec::new(), f)) } fn with_task_impl<'gcx, C, A, R>( @@ -232,6 +219,7 @@ impl DepGraph { create_task: fn(DepNode) -> OpenTask, finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>, DepNode, + Fingerprint, OpenTask) -> DepNodeIndex ) -> (R, DepNodeIndex) where @@ -271,26 +259,17 @@ impl DepGraph { profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) }; - let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task); - let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); let current_fingerprint = stable_hasher.finish(); - // Store the current fingerprint - { - let mut fingerprints = self.fingerprints.borrow_mut(); - - if dep_node_index.index() >= fingerprints.len() { - fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO); - } - - debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO, - "DepGraph::with_task() - Duplicate fingerprint \ - insertion for {:?}", key); - fingerprints[dep_node_index] = current_fingerprint; - } + let dep_node_index = finish_task_and_alloc_depnode( + &data.current, + key, + current_fingerprint, + open_task + ); // Determine the color of the new DepNode. if let Some(prev_index) = data.previous.node_to_index_opt(&key) { @@ -312,25 +291,7 @@ impl DepGraph { (result, dep_node_index) } else { - if key.kind.fingerprint_needed_for_crate_hash() { - let mut hcx = cx.get_stable_hashing_context(); - let result = task(cx, arg); - let mut stable_hasher = StableHasher::new(); - result.hash_stable(&mut hcx, &mut stable_hasher); - let fingerprint = stable_hasher.finish(); - - let mut fingerprints = self.fingerprints.borrow_mut(); - let dep_node_index = DepNodeIndex::new(fingerprints.len()); - fingerprints.push(fingerprint); - - debug_assert!(fingerprints[dep_node_index] == fingerprint, - "DepGraph::with_task() - Assigned fingerprint to \ - unexpected index for {:?}", key); - - (result, dep_node_index) - } else { - (task(cx, arg), DepNodeIndex::INVALID) - } + (task(cx, arg), DepNodeIndex::INVALID) } } @@ -381,7 +342,7 @@ impl DepGraph { { self.with_task_impl(key, cx, arg, false, task, |key| OpenTask::EvalAlways { node: key }, - |data, key, task| data.borrow_mut().complete_eval_always_task(key, task)) + |data, key, f, task| data.borrow_mut().complete_eval_always_task(key, task, f)) } #[inline] @@ -427,17 +388,8 @@ impl DepGraph { #[inline] pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - match self.fingerprints.borrow().get(dep_node_index) { - Some(&fingerprint) => fingerprint, - None => { - if let Some(ref data) = self.data { - let dep_node = data.current.borrow().nodes[dep_node_index]; - bug!("Could not find current fingerprint for {:?}", dep_node) - } else { - bug!("Could not find current fingerprint for {:?}", dep_node_index) - } - } - } + let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut(); + current.data[dep_node_index].fingerprint } pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> { @@ -498,17 +450,20 @@ impl DepGraph { pub fn serialize(&self) -> SerializedDepGraph { let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - let fingerprints = self.fingerprints.borrow().clone().convert_index_type(); - let nodes = current_dep_graph.nodes.clone().convert_index_type(); + let fingerprints: IndexVec<SerializedDepNodeIndex, _> = + current_dep_graph.data.iter().map(|d| d.fingerprint).collect(); + let nodes: IndexVec<SerializedDepNodeIndex, _> = + current_dep_graph.data.iter().map(|d| d.node).collect(); - let total_edge_count: usize = current_dep_graph.edges.iter() - .map(|v| v.len()) - .sum(); + let total_edge_count: usize = current_dep_graph.data.iter() + .map(|d| d.edges.len()) + .sum(); let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(total_edge_count); - for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() { + for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated() + .map(|(i, d)| (i, &d.edges)) { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index()))); @@ -704,31 +659,15 @@ impl DepGraph { // Someone else allocated it before us (dep_node_index, false) } else { + // Copy the fingerprint from the previous graph, + // so we don't have to recompute it + let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph - (current.alloc_node(*dep_node, current_deps), true) + (current.alloc_node(*dep_node, current_deps, fingerprint), true) } }; - // ... copying the fingerprint from the previous graph too, so we don't - // have to recompute it ... - { - let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); - let mut fingerprints = self.fingerprints.borrow_mut(); - - if dep_node_index.index() >= fingerprints.len() { - fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO); - } - - // Multiple threads can all write the same fingerprint here - #[cfg(not(parallel_queries))] - debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO, - "DepGraph::try_mark_green() - Duplicate fingerprint \ - insertion for {:?}", dep_node); - - fingerprints[dep_node_index] = fingerprint; - } - // ... emitting any stored diagnostic ... if did_allocation { // Only the thread which did the allocation emits the error messages @@ -814,7 +753,7 @@ impl DepGraph { pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { debug!("mark_loaded_from_cache({:?}, {})", - self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index], + self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node, state); self.data @@ -877,9 +816,15 @@ pub enum WorkProductFileKind { BytecodeCompressed, } +#[derive(Clone)] +struct DepNodeData { + node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint, +} + pub(super) struct CurrentDepGraph { - nodes: IndexVec<DepNodeIndex, DepNode>, - edges: IndexVec<DepNodeIndex, SmallVec<[DepNodeIndex; 8]>>, + data: IndexVec<DepNodeIndex, DepNodeData>, node_to_node_index: FxHashMap<DepNode, DepNodeIndex>, forbidden_edge: Option<EdgeFilter>, @@ -901,7 +846,7 @@ pub(super) struct CurrentDepGraph { } impl CurrentDepGraph { - fn new() -> CurrentDepGraph { + fn new(prev_graph_node_count: usize) -> CurrentDepGraph { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -924,10 +869,17 @@ impl CurrentDepGraph { None }; + // Pre-allocate the dep node structures. We over-allocate a little so + // that we hopefully don't have to re-allocate during this compilation + // session. + let new_node_count_estimate = (prev_graph_node_count * 115) / 100; + CurrentDepGraph { - nodes: IndexVec::new(), - edges: IndexVec::new(), - node_to_node_index: Default::default(), + data: IndexVec::with_capacity(new_node_count_estimate), + node_to_node_index: FxHashMap::with_capacity_and_hasher( + new_node_count_estimate, + Default::default(), + ), anon_id_seed: stable_hasher.finish(), forbidden_edge, total_read_count: 0, @@ -935,7 +887,12 @@ impl CurrentDepGraph { } } - fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { + fn complete_task( + &mut self, + key: DepNode, + task: OpenTask, + fingerprint: Fingerprint + ) -> DepNodeIndex { if let OpenTask::Regular(task) = task { let RegularOpenTask { node, @@ -956,17 +913,17 @@ impl CurrentDepGraph { // better in general. node.kind != DepKind::DefSpan && reads.iter().any(|&i| { - !(self.nodes[i].kind == DepKind::CrateMetadata || - self.nodes[i].kind == DepKind::Krate) + !(self.data[i].node.kind == DepKind::CrateMetadata || + self.data[i].node.kind == DepKind::Krate) }) { bug!("Input node {:?} with unexpected reads: {:?}", node, - reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>()) + reads.iter().map(|&i| self.data[i].node).collect::<Vec<_>>()) } } - self.alloc_node(node, reads) + self.alloc_node(node, reads, fingerprint) } else { bug!("complete_task() - Expected regular task to be popped") } @@ -984,7 +941,7 @@ impl CurrentDepGraph { let mut hasher = StableHasher::new(); for &read in reads.iter() { - let read_dep_node = self.nodes[read]; + let read_dep_node = self.data[read].node; ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher); @@ -1004,20 +961,25 @@ impl CurrentDepGraph { if let Some(&index) = self.node_to_node_index.get(&target_dep_node) { index } else { - self.alloc_node(target_dep_node, reads) + self.alloc_node(target_dep_node, reads, Fingerprint::ZERO) } } else { bug!("pop_anon_task() - Expected anonymous task to be popped") } } - fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { + fn complete_eval_always_task( + &mut self, + key: DepNode, + task: OpenTask, + fingerprint: Fingerprint + ) -> DepNodeIndex { if let OpenTask::EvalAlways { node, } = task { debug_assert_eq!(node, key); let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)]; - self.alloc_node(node, smallvec![krate_idx]) + self.alloc_node(node, smallvec![krate_idx], fingerprint) } else { bug!("complete_eval_always_task() - Expected eval always task to be popped"); } @@ -1036,7 +998,7 @@ impl CurrentDepGraph { if cfg!(debug_assertions) { if let Some(ref forbidden_edge) = self.forbidden_edge { let target = &task.node; - let source = self.nodes[source]; + let source = self.data[source].node; if forbidden_edge.test(&source, &target) { bug!("forbidden edge {:?} -> {:?} created", source, @@ -1063,15 +1025,18 @@ impl CurrentDepGraph { fn alloc_node(&mut self, dep_node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>) + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint) -> DepNodeIndex { - debug_assert_eq!(self.edges.len(), self.nodes.len()); - debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len()); + debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); - let dep_node_index = DepNodeIndex::new(self.nodes.len()); - self.nodes.push(dep_node); + let dep_node_index = DepNodeIndex::new(self.data.len()); + self.data.push(DepNodeData { + node: dep_node, + edges, + fingerprint + }); self.node_to_node_index.insert(dep_node, dep_node_index); - self.edges.push(edges); dep_node_index } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index d00d7b9f44e60..f574b757c40c9 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -41,21 +41,69 @@ pub(super) struct NodeCollector<'a, 'hir> { // We are collecting DepNode::HirBody hashes here so we can compute the // crate hash from then later on. - hir_body_nodes: Vec<(DefPathHash, DepNodeIndex)>, + hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, +} + +fn input_dep_node_and_hash<'a, I>( + dep_graph: &DepGraph, + hcx: &mut StableHashingContext<'a>, + def_node: DepNode, + input: I, +) -> (DepNodeIndex, Fingerprint) +where + I: HashStable<StableHashingContext<'a>>, +{ + let dep_node_index = dep_graph.input_task(def_node, &mut *hcx, &input).1; + + let hash = if dep_graph.is_fully_enabled() { + dep_graph.fingerprint_of(dep_node_index) + } else { + let mut stable_hasher = StableHasher::new(); + input.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() + }; + + (dep_node_index, hash) +} + +fn hir_dep_nodes<'a, I>( + dep_graph: &DepGraph, + hcx: &mut StableHashingContext<'a>, + def_path_hash: DefPathHash, + item_like: I, + hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, +) -> (DepNodeIndex, DepNodeIndex) +where + I: HashStable<StableHashingContext<'a>>, +{ + let sig = dep_graph.input_task( + def_path_hash.to_dep_node(DepKind::Hir), + &mut *hcx, + HirItemLike { item_like: &item_like, hash_bodies: false }, + ).1; + let (full, hash) = input_dep_node_and_hash( + dep_graph, + hcx, + def_path_hash.to_dep_node(DepKind::HirBody), + HirItemLike { item_like: &item_like, hash_bodies: true }, + ); + hir_body_nodes.push((def_path_hash, hash)); + (sig, full) } impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root(krate: &'hir Crate, dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, - hcx: StableHashingContext<'a>, + mut hcx: StableHashingContext<'a>, source_map: &'a SourceMap) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); + let mut hir_body_nodes = Vec::new(); + // Allocate DepNodes for the root module - let (root_mod_sig_dep_index, root_mod_full_dep_index); - { + let (root_mod_sig_dep_index, root_mod_full_dep_index) = { let Crate { ref module, // Crate attributes are not copied over to the root `Mod`, so hash @@ -73,28 +121,23 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { body_ids: _, } = *krate; - root_mod_sig_dep_index = dep_graph.input_task( - root_mod_def_path_hash.to_dep_node(DepKind::Hir), - &hcx, - HirItemLike { item_like: (module, attrs, span), hash_bodies: false }, - ).1; - root_mod_full_dep_index = dep_graph.input_task( - root_mod_def_path_hash.to_dep_node(DepKind::HirBody), - &hcx, - HirItemLike { item_like: (module, attrs, span), hash_bodies: true }, - ).1; - } + hir_dep_nodes( + dep_graph, + &mut hcx, + root_mod_def_path_hash, + (module, attrs, span), + &mut hir_body_nodes, + ) + }; { dep_graph.input_task( DepNode::new_no_params(DepKind::AllLocalTraitImpls), - &hcx, + &mut hcx, &krate.trait_impls, ); } - let hir_body_nodes = vec![(root_mod_def_path_hash, root_mod_full_dep_index)]; - let mut collector = NodeCollector { krate, source_map, @@ -129,9 +172,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let node_hashes = self .hir_body_nodes .iter() - .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, dep_node_index)| { + .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, hash)| { fingerprint.combine( - def_path_hash.0.combine(self.dep_graph.fingerprint_of(dep_node_index)) + def_path_hash.0.combine(hash) ) }); @@ -159,17 +202,19 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { source_file_names.sort_unstable(); - let (_, crate_dep_node_index) = self - .dep_graph - .input_task(DepNode::new_no_params(DepKind::Krate), - &self.hcx, - (((node_hashes, upstream_crates), source_file_names), - (commandline_args_hash, - crate_disambiguator.to_fingerprint()))); - - let svh = Svh::new(self.dep_graph - .fingerprint_of(crate_dep_node_index) - .to_smaller_hash()); + let crate_hash_input = ( + ((node_hashes, upstream_crates), source_file_names), + (commandline_args_hash, crate_disambiguator.to_fingerprint()) + ); + + let (_, crate_hash) = input_dep_node_and_hash( + self.dep_graph, + &mut self.hcx, + DepNode::new_no_params(DepKind::Krate), + crate_hash_input, + ); + + let svh = Svh::new(crate_hash.to_smaller_hash()); (self.map, svh) } @@ -251,19 +296,15 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - self.current_signature_dep_index = self.dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &self.hcx, - HirItemLike { item_like, hash_bodies: false }, - ).1; - - self.current_full_dep_index = self.dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::HirBody), - &self.hcx, - HirItemLike { item_like, hash_bodies: true }, - ).1; - - self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index)); + let (signature_dep_index, full_dep_index) = hir_dep_nodes( + self.dep_graph, + &mut self.hcx, + def_path_hash, + item_like, + &mut self.hir_body_nodes, + ); + self.current_signature_dep_index = signature_dep_index; + self.current_full_dep_index = full_dep_index; self.current_dep_node_owner = dep_node_owner; self.currently_in_body = false; From c5cba547db77f9c660ddfbe7b7a7ea9afb46f8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Sun, 23 Dec 2018 05:54:10 +0100 Subject: [PATCH 073/124] Use `entry` API to avoid double lookup when interning dep nodes --- src/librustc/dep_graph/graph.rs | 69 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8423c90447a25..5268c6cdd639b 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -6,6 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::sync::{Lrc, Lock}; use std::env; use std::hash::Hash; +use std::collections::hash_map::Entry; use ty::{self, TyCtxt}; use util::common::{ProfileQueriesMsg, profq_msg}; @@ -655,17 +656,13 @@ impl DepGraph { let (dep_node_index, did_allocation) = { let mut current = data.current.borrow_mut(); - if let Some(&dep_node_index) = current.node_to_node_index.get(&dep_node) { - // Someone else allocated it before us - (dep_node_index, false) - } else { - // Copy the fingerprint from the previous graph, - // so we don't have to recompute it - let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); - // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - (current.alloc_node(*dep_node, current_deps, fingerprint), true) - } + // Copy the fingerprint from the previous graph, + // so we don't have to recompute it + let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); + + // We allocating an entry for the node in the current dependency graph and + // adding all the appropriate edges imported from the previous graph + current.intern_node(*dep_node, current_deps, fingerprint) }; // ... emitting any stored diagnostic ... @@ -958,11 +955,7 @@ impl CurrentDepGraph { hash: fingerprint, }; - if let Some(&index) = self.node_to_node_index.get(&target_dep_node) { - index - } else { - self.alloc_node(target_dep_node, reads, Fingerprint::ZERO) - } + self.intern_node(target_dep_node, reads, Fingerprint::ZERO).0 } else { bug!("pop_anon_task() - Expected anonymous task to be popped") } @@ -1023,21 +1016,37 @@ impl CurrentDepGraph { }) } - fn alloc_node(&mut self, - dep_node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>, - fingerprint: Fingerprint) - -> DepNodeIndex { - debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); + fn alloc_node( + &mut self, + dep_node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint + ) -> DepNodeIndex { debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); - let dep_node_index = DepNodeIndex::new(self.data.len()); - self.data.push(DepNodeData { - node: dep_node, - edges, - fingerprint - }); - self.node_to_node_index.insert(dep_node, dep_node_index); - dep_node_index + self.intern_node(dep_node, edges, fingerprint).0 + } + + fn intern_node( + &mut self, + dep_node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint + ) -> (DepNodeIndex, bool) { + debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); + + match self.node_to_node_index.entry(dep_node) { + Entry::Occupied(entry) => (*entry.get(), false), + Entry::Vacant(entry) => { + let dep_node_index = DepNodeIndex::new(self.data.len()); + self.data.push(DepNodeData { + node: dep_node, + edges, + fingerprint + }); + entry.insert(dep_node_index); + (dep_node_index, true) + } + } } } From 216e8cca8e1298ec78c54a6102fcf3c89c9139c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com> Date: Mon, 31 Dec 2018 09:14:09 +0100 Subject: [PATCH 074/124] Address comments --- src/librustc/dep_graph/graph.rs | 10 +++++++--- src/librustc/hir/map/collector.rs | 16 +++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 5268c6cdd639b..961638151a2a8 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -189,7 +189,7 @@ impl DepGraph { reads: SmallVec::new(), read_set: Default::default(), })), - |data, key, f, task| data.borrow_mut().complete_task(key, task, f)) + |data, key, fingerprint, task| data.borrow_mut().complete_task(key, task, fingerprint)) } /// Creates a new dep-graph input with value `input` @@ -207,7 +207,9 @@ impl DepGraph { self.with_task_impl(key, cx, input, true, identity_fn, |_| OpenTask::Ignore, - |data, key, f, _| data.borrow_mut().alloc_node(key, SmallVec::new(), f)) + |data, key, fingerprint, _| { + data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) + }) } fn with_task_impl<'gcx, C, A, R>( @@ -343,7 +345,9 @@ impl DepGraph { { self.with_task_impl(key, cx, arg, false, task, |key| OpenTask::EvalAlways { node: key }, - |data, key, f, task| data.borrow_mut().complete_eval_always_task(key, task, f)) + |data, key, fingerprint, task| { + data.borrow_mut().complete_eval_always_task(key, task, fingerprint) + }) } #[inline] diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index f574b757c40c9..78acea9f58814 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -47,13 +47,13 @@ pub(super) struct NodeCollector<'a, 'hir> { fn input_dep_node_and_hash<'a, I>( dep_graph: &DepGraph, hcx: &mut StableHashingContext<'a>, - def_node: DepNode, + dep_node: DepNode, input: I, ) -> (DepNodeIndex, Fingerprint) where I: HashStable<StableHashingContext<'a>>, { - let dep_node_index = dep_graph.input_task(def_node, &mut *hcx, &input).1; + let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; let hash = if dep_graph.is_fully_enabled() { dep_graph.fingerprint_of(dep_node_index) @@ -66,7 +66,7 @@ where (dep_node_index, hash) } -fn hir_dep_nodes<'a, I>( +fn alloc_hir_dep_nodes<'a, I>( dep_graph: &DepGraph, hcx: &mut StableHashingContext<'a>, def_path_hash: DefPathHash, @@ -121,7 +121,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { body_ids: _, } = *krate; - hir_dep_nodes( + alloc_hir_dep_nodes( dep_graph, &mut hcx, root_mod_def_path_hash, @@ -172,10 +172,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let node_hashes = self .hir_body_nodes .iter() - .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, hash)| { - fingerprint.combine( - def_path_hash.0.combine(hash) - ) + .fold(Fingerprint::ZERO, |combined_fingerprint, &(def_path_hash, fingerprint)| { + combined_fingerprint.combine(def_path_hash.0.combine(fingerprint)) }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { @@ -296,7 +294,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let (signature_dep_index, full_dep_index) = hir_dep_nodes( + let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes( self.dep_graph, &mut self.hcx, def_path_hash, From 21e0948c97765e36b0c6ac376fc48977943ef70d Mon Sep 17 00:00:00 2001 From: ian <me@iany.me> Date: Wed, 26 Dec 2018 13:01:30 +0800 Subject: [PATCH 075/124] Fix inconsistent Clone documentation. Use function pointer as the example to demonstrate how to implement Clone for Copy types. refs #57123 --- src/libcore/clone.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 74b3ce4f978b9..ed90b7de26417 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -53,6 +53,17 @@ /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d /// implementation of [`clone`] calls [`clone`] on each field. /// +/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on +/// generic parameters. +/// +/// ``` +/// // `derive` implements Clone for Reading<T> when T is Clone. +/// #[derive(Clone)] +/// struct Reading<T> { +/// frequency: T, +/// } +/// ``` +/// /// ## How can I implement `Clone`? /// /// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally: @@ -60,21 +71,21 @@ /// Manual implementations should be careful to uphold this invariant; however, unsafe code /// must not rely on it to ensure memory safety. /// -/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard -/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of -/// `Clone` cannot be `derive`d, but can be implemented as: +/// An example is a generic struct holding a function pointer. In this case, the +/// implementation of `Clone` cannot be `derive`d, but can be implemented as: /// /// [`Copy`]: ../../std/marker/trait.Copy.html /// [`clone`]: trait.Clone.html#tymethod.clone /// /// ``` -/// #[derive(Copy)] -/// struct Stats { -/// frequencies: [i32; 100], -/// } +/// struct Generate<T>(fn() -> T); +/// +/// impl<T> Copy for Generate<T> {} /// -/// impl Clone for Stats { -/// fn clone(&self) -> Stats { *self } +/// impl<T> Clone for Generate<T> { +/// fn clone(&self) -> Self { +/// *self +/// } /// } /// ``` /// From 7e454d280af1f50cfbbc34d91f1cbe14b3b38c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Sat, 29 Dec 2018 17:19:22 -0800 Subject: [PATCH 076/124] Suggest using raw identifiers in 2018 edition when using keywords --- src/libsyntax/parse/parser.rs | 13 ++++++++++++- .../edition-keywords-2015-2018-expansion.stderr | 6 +++++- .../edition-keywords-2018-2015-parsing.stderr | 12 ++++++++++-- .../edition-keywords-2018-2018-expansion.stderr | 6 +++++- .../edition-keywords-2018-2018-parsing.stderr | 12 ++++++++++-- .../ui/rust-2018/dyn-trait-compatibility.stderr | 6 +++++- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 52da8a072c751..1a0366932dbf6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -798,7 +798,18 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(self.span, &format!("expected identifier, found {}", self.this_token_descr())); - if let Some(token_descr) = self.token_descr() { + if let (true, token::Ident(ref s, false), true) = ( + self.span.rust_2018(), + &self.token, + self.token.is_used_keyword() || self.token.is_unused_keyword(), + ) { + err.span_suggestion_with_applicability( + self.span, + "you can escape reserved keywords to use them as identifiers", + format!("r#{}", s.to_string()), + Applicability::MaybeIncorrect, + ); + } else if let Some(token_descr) = self.token_descr() { err.span_label(self.span, format!("expected identifier, found {}", token_descr)); } else { err.span_label(self.span, "expected identifier"); diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index 5dd7030c77ec6..c598e2de4c62f 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -2,9 +2,13 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5 | LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword - | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword + | ^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +help: you can escape reserved keywords to use them as identifiers + | +LL | ( ) => ( pub fn r#async ( ) { } ) + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index bd49948eb9531..5f89dc5cfbbb0 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -2,13 +2,21 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ +help: you can escape reserved keywords to use them as identifiers + | +LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31 diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index 44d0e78d06a46..f0878f69b8f03 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -2,9 +2,13 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5 | LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword + | ^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +help: you can escape reserved keywords to use them as identifiers + | +LL | ( ) => ( pub fn r#async ( ) { } ) + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 8e596f743d7f7..994edb50f0d95 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -2,13 +2,21 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ expected identifier, found reserved keyword + | ^^^^^ +help: you can escape reserved keywords to use them as identifiers + | +LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31 diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr index bd72f9c6786b2..b7bcf98743501 100644 --- a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr +++ b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr @@ -2,7 +2,11 @@ error: expected identifier, found keyword `dyn` --> $DIR/dyn-trait-compatibility.rs:4:16 | LL | type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` - | ^^^ expected identifier, found keyword + | ^^^ +help: you can escape reserved keywords to use them as identifiers + | +LL | type A1 = dyn::r#dyn; //~ERROR expected identifier, found keyword `dyn` + | ^^^^^ error: expected identifier, found `<` --> $DIR/dyn-trait-compatibility.rs:5:14 From 9ee58ffa6963e0d64dba061065cbf580f4923dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Sun, 30 Dec 2018 11:52:15 -0800 Subject: [PATCH 077/124] Address review comments - Suggest raw ident escaping in all editions - Keep primary label in all cases --- src/libsyntax/parse/parser.rs | 25 ++++++++++--------- ...dition-keywords-2015-2018-expansion.stderr | 2 +- .../edition-keywords-2018-2015-parsing.stderr | 4 +-- ...dition-keywords-2018-2018-expansion.stderr | 2 +- .../edition-keywords-2018-2018-parsing.stderr | 4 +-- src/test/ui/issues/issue-28433.stderr | 4 +++ src/test/ui/issues/issue-44406.stderr | 4 +++ .../ui/lifetime_starts_expressions.stderr | 4 +++ ...ed-types-project-from-hrtb-explicit.stderr | 4 +++ .../ui/parser/bad-value-ident-false.stderr | 4 +++ .../ui/parser/bad-value-ident-true.stderr | 4 +++ src/test/ui/parser/issue-15980.stderr | 4 +++ src/test/ui/parser/keyword.stderr | 4 +++ src/test/ui/parser/macro-keyword.stderr | 4 +++ .../ui/parser/removed-syntax-field-let.stderr | 4 +++ .../use-as-where-use-ends-with-mod-sep.stderr | 4 +++ .../rust-2018/dyn-trait-compatibility.stderr | 2 +- .../try-block/try-block-in-edition2015.stderr | 4 +++ 18 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1a0366932dbf6..7c471fdebb3a0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -798,18 +798,19 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(self.span, &format!("expected identifier, found {}", self.this_token_descr())); - if let (true, token::Ident(ref s, false), true) = ( - self.span.rust_2018(), - &self.token, - self.token.is_used_keyword() || self.token.is_unused_keyword(), - ) { - err.span_suggestion_with_applicability( - self.span, - "you can escape reserved keywords to use them as identifiers", - format!("r#{}", s.to_string()), - Applicability::MaybeIncorrect, - ); - } else if let Some(token_descr) = self.token_descr() { + if let token::Ident(ident, false) = &self.token { + if ident.is_reserved() && !ident.is_path_segment_keyword() && + ident.name != keywords::Underscore.name() + { + err.span_suggestion_with_applicability( + self.span, + "you can escape reserved keywords to use them as identifiers", + format!("r#{}", ident), + Applicability::MaybeIncorrect, + ); + } + } + if let Some(token_descr) = self.token_descr() { err.span_label(self.span, format!("expected identifier, found {}", token_descr)); } else { err.span_label(self.span, "expected identifier"); diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index c598e2de4c62f..af1ac19c837d5 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -2,7 +2,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5 | LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index 5f89dc5cfbbb0..52399362482bc 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -2,7 +2,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ + | ^^^^^ expected identifier, found reserved keyword help: you can escape reserved keywords to use them as identifiers | LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` @@ -12,7 +12,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ + | ^^^^^ expected identifier, found reserved keyword help: you can escape reserved keywords to use them as identifiers | LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index f0878f69b8f03..d997c3d8a421a 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -2,7 +2,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5 | LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 994edb50f0d95..1621368870a52 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -2,7 +2,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ + | ^^^^^ expected identifier, found reserved keyword help: you can escape reserved keywords to use them as identifiers | LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` @@ -12,7 +12,7 @@ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` - | ^^^^^ + | ^^^^^ expected identifier, found reserved keyword help: you can escape reserved keywords to use them as identifiers | LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` diff --git a/src/test/ui/issues/issue-28433.stderr b/src/test/ui/issues/issue-28433.stderr index 97df6db2b5215..d3cba3aae7101 100644 --- a/src/test/ui/issues/issue-28433.stderr +++ b/src/test/ui/issues/issue-28433.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `pub` | LL | pub duck, | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#pub duck, + | ^^^^^ error: expected one of `(`, `,`, `=`, `{`, or `}`, found `duck` --> $DIR/issue-28433.rs:4:9 diff --git a/src/test/ui/issues/issue-44406.stderr b/src/test/ui/issues/issue-44406.stderr index 45ea586373c3c..105dbb677dc02 100644 --- a/src/test/ui/issues/issue-44406.stderr +++ b/src/test/ui/issues/issue-44406.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `true` | LL | foo!(true); //~ ERROR expected type, found keyword | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | foo!(r#true); //~ ERROR expected type, found keyword + | ^^^^^^ error: expected type, found keyword `true` --> $DIR/issue-44406.rs:8:10 diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr index 20efc1fab56b1..fa0a7ac002b2f 100644 --- a/src/test/ui/lifetime_starts_expressions.stderr +++ b/src/test/ui/lifetime_starts_expressions.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `loop` | LL | loop { break 'label: loop { break 'label 42; }; } | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | loop { break 'label: r#loop { break 'label 42; }; } + | ^^^^^^ error: expected type, found keyword `loop` --> $DIR/lifetime_starts_expressions.rs:6:26 diff --git a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr index 51b1e71a1bb90..ceea4625e3eb3 100644 --- a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr +++ b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `for` | LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A) | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A) + | ^^^^^ error: expected one of `::` or `>`, found `Foo` --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:29 diff --git a/src/test/ui/parser/bad-value-ident-false.stderr b/src/test/ui/parser/bad-value-ident-false.stderr index a78437a05f425..1a5c982a43dbc 100644 --- a/src/test/ui/parser/bad-value-ident-false.stderr +++ b/src/test/ui/parser/bad-value-ident-false.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `false` | LL | fn false() { } //~ ERROR expected identifier, found keyword `false` | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#false() { } //~ ERROR expected identifier, found keyword `false` + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/bad-value-ident-true.stderr b/src/test/ui/parser/bad-value-ident-true.stderr index 948fa4db50e8e..f431706ccd76b 100644 --- a/src/test/ui/parser/bad-value-ident-true.stderr +++ b/src/test/ui/parser/bad-value-ident-true.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `true` | LL | fn true() { } //~ ERROR expected identifier, found keyword `true` | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#true() { } //~ ERROR expected identifier, found keyword `true` + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-15980.stderr b/src/test/ui/parser/issue-15980.stderr index 748f21016a33b..96f3b03dc9240 100644 --- a/src/test/ui/parser/issue-15980.stderr +++ b/src/test/ui/parser/issue-15980.stderr @@ -6,6 +6,10 @@ LL | Err(ref e) if e.kind == io::EndOfFile { LL | //~^ NOTE while parsing this struct LL | return | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#return + | error: expected one of `.`, `=>`, `?`, or an operator, found `_` --> $DIR/issue-15980.rs:15:9 diff --git a/src/test/ui/parser/keyword.stderr b/src/test/ui/parser/keyword.stderr index d97f6c5ce5aff..1c729ff083352 100644 --- a/src/test/ui/parser/keyword.stderr +++ b/src/test/ui/parser/keyword.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `break` | LL | pub mod break { | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#break { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/macro-keyword.stderr b/src/test/ui/parser/macro-keyword.stderr index 0dca30a60d1da..d3edb04c11951 100644 --- a/src/test/ui/parser/macro-keyword.stderr +++ b/src/test/ui/parser/macro-keyword.stderr @@ -3,6 +3,10 @@ error: expected identifier, found reserved keyword `macro` | LL | fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#macro() { //~ ERROR expected identifier, found reserved keyword `macro` + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr index bec50e59664d6..0d489beae123a 100644 --- a/src/test/ui/parser/removed-syntax-field-let.stderr +++ b/src/test/ui/parser/removed-syntax-field-let.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `let` | LL | let foo: (), | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#let foo: (), + | ^^^^^ error: expected `:`, found `foo` --> $DIR/removed-syntax-field-let.rs:4:9 diff --git a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr index 3be31ce9cec63..51e1a02cbd763 100644 --- a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr +++ b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `as` | LL | use std::any:: as foo; //~ ERROR expected identifier, found keyword `as` | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use std::any:: r#as foo; //~ ERROR expected identifier, found keyword `as` + | ^^^^ error: expected one of `::`, `;`, or `as`, found `foo` --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:19 diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr index b7bcf98743501..6be0052046583 100644 --- a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr +++ b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr @@ -2,7 +2,7 @@ error: expected identifier, found keyword `dyn` --> $DIR/dyn-trait-compatibility.rs:4:16 | LL | type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` - | ^^^ + | ^^^ expected identifier, found keyword help: you can escape reserved keywords to use them as identifiers | LL | type A1 = dyn::r#dyn; //~ERROR expected identifier, found keyword `dyn` diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index b16aa59090d04..63650086bcaa9 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -6,6 +6,10 @@ LL | let try_result: Option<_> = try { LL | //~^ ERROR expected struct, variant or union type, found macro `try` LL | let x = 5; //~ ERROR expected identifier, found keyword | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#let x = 5; //~ ERROR expected identifier, found keyword + | ^^^^^ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 From fdedfc01eda4a9bada9b6dab9c390fc9d9187e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Mon, 31 Dec 2018 08:41:05 -0800 Subject: [PATCH 078/124] Update tests after rebase --- src/test/ui/issues/issue-57198.stderr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/ui/issues/issue-57198.stderr b/src/test/ui/issues/issue-57198.stderr index c4d297b2d95eb..2ab552ccbd3c8 100644 --- a/src/test/ui/issues/issue-57198.stderr +++ b/src/test/ui/issues/issue-57198.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `for` | LL | m::for(); | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | m::r#for(); + | ^^^^^ error: aborting due to previous error From 7cf446823219a63a62a4d76cbeb85b85c31392d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Thu, 27 Dec 2018 10:40:06 -0800 Subject: [PATCH 079/124] Account for `\xFF` and `\u{FF}` sequences in string format errors --- src/libsyntax_ext/format.rs | 45 ++++++++++++++++++ src/test/ui/fmt/format-string-error-2.rs | 15 ++++++ src/test/ui/fmt/format-string-error-2.stderr | 48 +++++++++++++++++++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index ac1402a0faaa5..3a5f0ec07e76c 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -808,12 +808,57 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } ('\\', Some((next_pos, 'n'))) | ('\\', Some((next_pos, 't'))) | + ('\\', Some((next_pos, '0'))) | ('\\', Some((next_pos, '\\'))) | ('\\', Some((next_pos, '\''))) | ('\\', Some((next_pos, '\"'))) => { skips.push(*next_pos); let _ = s.next(); } + ('\\', Some((_, 'x'))) if !is_raw => { + for _ in 0..3 { // consume `\xAB` literal + if let Some((pos, _)) = s.next() { + skips.push(pos); + } else { + break; + } + } + } + ('\\', Some((_, 'u'))) if !is_raw => { + if let Some((pos, _)) = s.next() { + skips.push(pos); + } + if let Some((next_pos, next_c)) = s.next() { + if next_c == '{' { + skips.push(next_pos); + let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` + while let (Some((next_pos, c)), true) = (s.next(), i < 7) { + if c.is_digit(16) { + skips.push(next_pos); + } else if c == '}' { + skips.push(next_pos); + break; + } else { + break; + } + i += 1; + } + } else if next_c.is_digit(16) { + skips.push(next_pos); + // We suggest adding `{` and `}` when appropriate, accept it here as if it + // were correct + let mut i = 0; // consume up to 6 hexanumeric chars + while let (Some((next_pos, c)), _) = (s.next(), i < 6) { + if c.is_digit(16) { + skips.push(next_pos); + } else { + break; + } + i += 1; + } + } + } + } _ if eat_ws => { // `take_while(|c| c.is_whitespace())` eat_ws = false; } diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index 3c6c15c06bb2a..5c25ae502ff6d 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -69,4 +69,19 @@ raw { \n //~^^ ERROR invalid format string println!("\t{}"); //~^ ERROR 1 positional argument in format string + + // note: `\x7B` is `{` + println!("\x7B}\u{8} {", 1); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + + println!("\x7B}\u8 {", 1); + //~^ ERROR incorrect unicode escape sequence + //~| ERROR argument never used + + // note: raw strings don't escape `\xFF` and `\u{FF}` sequences + println!(r#"\x7B}\u{8} {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found + + println!(r#"\x7B}\u8 {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found } diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index face0bc0f5f68..ae62ed66338bc 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -1,3 +1,15 @@ +error: incorrect unicode escape sequence + --> $DIR/format-string-error-2.rs:77:20 + | +LL | println!("/x7B}/u8 {", 1); + | ^^ + | +help: format of unicode escape sequences is `/u{…}` + --> $DIR/format-string-error-2.rs:77:20 + | +LL | println!("/x7B}/u8 {", 1); + | ^^ + error: invalid format string: expected `'}'`, found `'a'` --> $DIR/format-string-error-2.rs:5:5 | @@ -139,5 +151,39 @@ error: 1 positional argument in format string, but no arguments were given LL | println!("/t{}"); | ^^ -error: aborting due to 14 previous errors +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error-2.rs:74:27 + | +LL | println!("/x7B}/u{8} {", 1); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: argument never used + --> $DIR/format-string-error-2.rs:77:28 + | +LL | println!("/x7B}/u8 {", 1); + | ------------ ^ argument never used + | | + | formatting specifier missing + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:82:21 + | +LL | println!(r#"/x7B}/u{8} {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:85:21 + | +LL | println!(r#"/x7B}/u8 {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 19 previous errors From 73ba9d84f2e3ba8c330f02826e969745112ffa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Thu, 27 Dec 2018 11:21:47 -0800 Subject: [PATCH 080/124] Use structured suggestion for braceless unicode escape squence --- src/libsyntax/parse/lexer/mod.rs | 36 +++++++++++++++---- src/libsyntax_ext/format.rs | 4 +-- src/test/ui/fmt/format-string-error-2.stderr | 10 ++---- .../ui/parser/issue-23620-invalid-escapes.rs | 3 ++ .../parser/issue-23620-invalid-escapes.stderr | 10 +++++- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index d13de0029682e..fb46f7a08b935 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -945,12 +945,36 @@ impl<'a> StringReader<'a> { self.scan_unicode_escape(delim) && !ascii_only } else { let span = self.mk_sp(start, self.pos); - self.sess.span_diagnostic - .struct_span_err(span, "incorrect unicode escape sequence") - .span_help(span, - "format of unicode escape sequences is \ - `\\u{…}`") - .emit(); + let mut suggestion = "\\u{".to_owned(); + let mut err = self.sess.span_diagnostic.struct_span_err( + span, + "incorrect unicode escape sequence", + ); + let mut i = 0; + while let (Some(ch), true) = (self.ch, i < 6) { + if ch.is_digit(16) { + suggestion.push(ch); + self.bump(); + i += 1; + } else { + break; + } + } + if i != 0 { + suggestion.push('}'); + err.span_suggestion_with_applicability( + self.mk_sp(start, self.pos), + "format of unicode escape sequences uses braces", + suggestion, + Applicability::MaybeIncorrect, + ); + } else { + err.span_help( + span, + "format of unicode escape sequences is `\\u{…}`", + ); + } + err.emit(); false }; if ascii_only { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 3a5f0ec07e76c..c11f27f3ed589 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -845,8 +845,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } } else if next_c.is_digit(16) { skips.push(next_pos); - // We suggest adding `{` and `}` when appropriate, accept it here as if it - // were correct + // We suggest adding `{` and `}` when appropriate, accept it here as if + // it were correct let mut i = 0; // consume up to 6 hexanumeric chars while let (Some((next_pos, c)), _) = (s.next(), i < 6) { if c.is_digit(16) { diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index ae62ed66338bc..baab8529940c5 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -2,13 +2,9 @@ error: incorrect unicode escape sequence --> $DIR/format-string-error-2.rs:77:20 | LL | println!("/x7B}/u8 {", 1); - | ^^ - | -help: format of unicode escape sequences is `/u{…}` - --> $DIR/format-string-error-2.rs:77:20 - | -LL | println!("/x7B}/u8 {", 1); - | ^^ + | ^^- + | | + | help: format of unicode escape sequences uses braces: `/u{8}` error: invalid format string: expected `'}'`, found `'a'` --> $DIR/format-string-error-2.rs:5:5 diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs index 6895a926b4f0c..f8a2f1cc7e6c9 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.rs +++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs @@ -35,4 +35,7 @@ fn main() { //~^ ERROR invalid character in numeric character escape: //~^^ ERROR form of character escape may only be used with characters in the range [\x00-\x7f] //~^^^ ERROR incorrect unicode escape sequence + + let _ = "\u8f"; + //~^ ERROR incorrect unicode escape sequence } diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index b1a5764e891d8..025b392627d0f 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -118,5 +118,13 @@ help: format of unicode escape sequences is `/u{…}` LL | let _ = "/xf /u"; | ^^ -error: aborting due to 17 previous errors +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:39:14 + | +LL | let _ = "/u8f"; + | ^^-- + | | + | help: format of unicode escape sequences uses braces: `/u{8f}` + +error: aborting due to 18 previous errors From 0ed7ced1d846d6131be2b6c403a2d012c330fdb2 Mon Sep 17 00:00:00 2001 From: Andy Russell <arussell123@gmail.com> Date: Thu, 20 Dec 2018 18:10:46 -0500 Subject: [PATCH 081/124] use structured suggestions for nonexistent fields --- src/librustc_typeck/check/mod.rs | 24 +++++++++++++------ src/test/ui/did_you_mean/issue-36798.stderr | 2 +- .../issue-42599_available_fields_note.stderr | 4 ++-- src/test/ui/error-codes/ex-E0612.stderr | 2 +- ...73-zero-padded-tuple-struct-indices.stderr | 2 +- src/test/ui/issues/issue-4736.stderr | 2 +- src/test/ui/issues/issue-56199.stderr | 8 +++---- src/test/ui/issues/issue-56835.stderr | 2 +- src/test/ui/rmeta_meta_main.stderr | 2 +- .../struct-fields-hints-no-dupe.stderr | 2 +- .../ui/structs/struct-fields-hints.stderr | 2 +- src/test/ui/structs/struct-fields-typo.rs | 5 ++-- src/test/ui/structs/struct-fields-typo.stderr | 4 ++-- .../suggestions/suggest-private-fields.stderr | 6 ++--- .../ui/tuple/tuple-index-not-tuple.stderr | 2 +- .../ui/tuple/tuple-index-out-of-bounds.stderr | 2 +- src/test/ui/union/union-suggest-field.rs | 6 ++++- src/test/ui/union/union-suggest-field.stderr | 8 +++---- 18 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 36de41ef8a170..d78d7273a36e6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3435,8 +3435,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(suggested_field_name) = Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![]) { - err.span_label(field.span, - format!("did you mean `{}`?", suggested_field_name)); + err.span_suggestion_with_applicability( + field.span, + "a field with a similar name exists", + suggested_field_name.to_string(), + Applicability::MaybeIncorrect, + ); } else { err.span_label(field.span, "unknown field"); let struct_variant_def = def.non_enum_variant(); @@ -3563,8 +3567,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field_name) = Self::suggest_field_name(variant, &field.ident.as_str(), skip_fields.collect()) { - err.span_label(field.ident.span, - format!("field does not exist - did you mean `{}`?", field_name)); + err.span_suggestion_with_applicability( + field.ident.span, + "a field with a similar name exists", + field_name.to_string(), + Applicability::MaybeIncorrect, + ); } else { match ty.sty { ty::Adt(adt, ..) => { @@ -5210,13 +5218,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(adt_def) = adt_def { match adt_def.adt_kind() { AdtKind::Enum => { - err.note("did you mean to use one of the enum's variants?"); + err.help("did you mean to use one of the enum's variants?"); }, AdtKind::Struct | AdtKind::Union => { - err.span_label( + err.span_suggestion_with_applicability( span, - format!("did you mean `Self {{ /* fields */ }}`?"), + "use curly brackets", + String::from("Self { /* fields */ }"), + Applicability::HasPlaceholders, ); } } diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index 41dc15c1b81e7..8273fad476462 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:7:7 | LL | f.baz; //~ ERROR no field - | ^^^ did you mean `bar`? + | ^^^ help: a field with a similar name exists: `bar` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr index 808ff1670da09..e5dd61c45d662 100644 --- a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr +++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `submodule::Demo` has no field named `inocently_mispellable --> $DIR/issue-42599_available_fields_note.rs:16:39 | LL | Self { secret_integer: 2, inocently_mispellable: () } - | ^^^^^^^^^^^^^^^^^^^^^ field does not exist - did you mean `innocently_misspellable`? + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` error[E0560]: struct `submodule::Demo` has no field named `egregiously_nonexistent_field` --> $DIR/issue-42599_available_fields_note.rs:21:39 @@ -16,7 +16,7 @@ error[E0609]: no field `inocently_mispellable` on type `submodule::Demo` --> $DIR/issue-42599_available_fields_note.rs:32:41 | LL | let innocent_field_misaccess = demo.inocently_mispellable; - | ^^^^^^^^^^^^^^^^^^^^^ did you mean `innocently_misspellable`? + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` error[E0609]: no field `egregiously_nonexistent_field` on type `submodule::Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 diff --git a/src/test/ui/error-codes/ex-E0612.stderr b/src/test/ui/error-codes/ex-E0612.stderr index e65e8bd814266..0f498d1643905 100644 --- a/src/test/ui/error-codes/ex-E0612.stderr +++ b/src/test/ui/error-codes/ex-E0612.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `1` on type `Foo` --> $DIR/ex-E0612.rs:5:6 | LL | y.1; //~ ERROR no field `1` on type `Foo` - | ^ did you mean `0`? + | ^ help: a field with a similar name exists: `0` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr index 6e8d1ef2f7b9e..5e1b816defda3 100644 --- a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr +++ b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `00` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 | LL | let _condemned = justice.00; - | ^^ did you mean `0`? + | ^^ help: a field with a similar name exists: `0` error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index eac7e65064d49..39c649ba3e0e7 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; //~ ERROR struct `NonCopyable` has no field named `p` - | ^ field does not exist - did you mean `0`? + | ^ help: a field with a similar name exists: `0` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr index 9503183deb97c..7aaf8e4ac2f14 100644 --- a/src/test/ui/issues/issue-56199.stderr +++ b/src/test/ui/issues/issue-56199.stderr @@ -4,7 +4,7 @@ error: the `Self` constructor can only be used with tuple or unit structs LL | let _ = Self; | ^^^^ | - = note: did you mean to use one of the enum's variants? + = help: did you mean to use one of the enum's variants? error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:8:17 @@ -12,19 +12,19 @@ error: the `Self` constructor can only be used with tuple or unit structs LL | let _ = Self(); | ^^^^ | - = note: did you mean to use one of the enum's variants? + = help: did you mean to use one of the enum's variants? error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:15:17 | LL | let _ = Self; - | ^^^^ did you mean `Self { /* fields */ }`? + | ^^^^ help: use curly brackets: `Self { /* fields */ }` error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:17:17 | LL | let _ = Self(); - | ^^^^ did you mean `Self { /* fields */ }`? + | ^^^^ help: use curly brackets: `Self { /* fields */ }` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr index 21ecbf05dc72f..f9fdf23af9715 100644 --- a/src/test/ui/issues/issue-56835.stderr +++ b/src/test/ui/issues/issue-56835.stderr @@ -2,7 +2,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56835.rs:4:12 | LL | fn bar(Self(foo): Self) {} - | ^^^^^^^^^ did you mean `Self { /* fields */ }`? + | ^^^^^^^^^ help: use curly brackets: `Self { /* fields */ }` error[E0164]: expected tuple struct/variant, found self constructor `Self` --> $DIR/issue-56835.rs:4:12 diff --git a/src/test/ui/rmeta_meta_main.stderr b/src/test/ui/rmeta_meta_main.stderr index b7d7f89cfbb4c..bed9076d84cbe 100644 --- a/src/test/ui/rmeta_meta_main.stderr +++ b/src/test/ui/rmeta_meta_main.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `rmeta_meta::Foo` has no field named `field2` --> $DIR/rmeta_meta_main.rs:13:19 | LL | let _ = Foo { field2: 42 }; //~ ERROR struct `rmeta_meta::Foo` has no field named `field2` - | ^^^^^^ field does not exist - did you mean `field`? + | ^^^^^^ help: a field with a similar name exists: `field` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fields-hints-no-dupe.stderr b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr index 105f330463a94..1a88f269347c2 100644 --- a/src/test/ui/structs/struct-fields-hints-no-dupe.stderr +++ b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints-no-dupe.rs:10:9 | LL | bar : 42, - | ^^^ field does not exist - did you mean `barr`? + | ^^^ help: a field with a similar name exists: `barr` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fields-hints.stderr b/src/test/ui/structs/struct-fields-hints.stderr index d713030563102..3b8a2b5c7bad0 100644 --- a/src/test/ui/structs/struct-fields-hints.stderr +++ b/src/test/ui/structs/struct-fields-hints.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints.rs:10:9 | LL | bar : 42, - | ^^^ field does not exist - did you mean `car`? + | ^^^ help: a field with a similar name exists: `car` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fields-typo.rs b/src/test/ui/structs/struct-fields-typo.rs index b435a0a47773d..0e9b2ae5145d7 100644 --- a/src/test/ui/structs/struct-fields-typo.rs +++ b/src/test/ui/structs/struct-fields-typo.rs @@ -8,7 +8,8 @@ fn main() { foo: 0, bar: 0.5, }; - let x = foo.baa;//~ no field `baa` on type `BuildData` - //~^ did you mean `bar`? + let x = foo.baa; //~ ERROR no field `baa` on type `BuildData` + //~| HELP a field with a similar name exists + //~| SUGGESTION bar println!("{}", x); } diff --git a/src/test/ui/structs/struct-fields-typo.stderr b/src/test/ui/structs/struct-fields-typo.stderr index 93127ab5beb6e..c2fab714f7c15 100644 --- a/src/test/ui/structs/struct-fields-typo.stderr +++ b/src/test/ui/structs/struct-fields-typo.stderr @@ -1,8 +1,8 @@ error[E0609]: no field `baa` on type `BuildData` --> $DIR/struct-fields-typo.rs:11:17 | -LL | let x = foo.baa;//~ no field `baa` on type `BuildData` - | ^^^ did you mean `bar`? +LL | let x = foo.baa; //~ ERROR no field `baa` on type `BuildData` + | ^^^ help: a field with a similar name exists: `bar` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/suggestions/suggest-private-fields.stderr index 5f0176473ea74..524558e0ec564 100644 --- a/src/test/ui/suggestions/suggest-private-fields.stderr +++ b/src/test/ui/suggestions/suggest-private-fields.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `xc::B` has no field named `aa` --> $DIR/suggest-private-fields.rs:15:9 | LL | aa: 20, - | ^^ field does not exist - did you mean `a`? + | ^^ help: a field with a similar name exists: `a` error[E0560]: struct `xc::B` has no field named `bb` --> $DIR/suggest-private-fields.rs:17:9 @@ -16,13 +16,13 @@ error[E0560]: struct `A` has no field named `aa` --> $DIR/suggest-private-fields.rs:22:9 | LL | aa: 20, - | ^^ field does not exist - did you mean `a`? + | ^^ help: a field with a similar name exists: `a` error[E0560]: struct `A` has no field named `bb` --> $DIR/suggest-private-fields.rs:24:9 | LL | bb: 20, - | ^^ field does not exist - did you mean `b`? + | ^^ help: a field with a similar name exists: `b` error: aborting due to 4 previous errors diff --git a/src/test/ui/tuple/tuple-index-not-tuple.stderr b/src/test/ui/tuple/tuple-index-not-tuple.stderr index ab9ac4c4142fe..a1bcdfaedbc60 100644 --- a/src/test/ui/tuple/tuple-index-not-tuple.stderr +++ b/src/test/ui/tuple/tuple-index-not-tuple.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `0` on type `Point` --> $DIR/tuple-index-not-tuple.rs:6:12 | LL | origin.0; - | ^ did you mean `x`? + | ^ help: a field with a similar name exists: `x` error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 diff --git a/src/test/ui/tuple/tuple-index-out-of-bounds.stderr b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr index 86e977a01b76d..7d7c5cd7892ea 100644 --- a/src/test/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `2` on type `Point` --> $DIR/tuple-index-out-of-bounds.rs:7:12 | LL | origin.2; - | ^ did you mean `0`? + | ^ help: a field with a similar name exists: `0` error[E0609]: no field `2` on type `({integer}, {integer})` --> $DIR/tuple-index-out-of-bounds.rs:12:11 diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs index ad527a9791802..b2d8c0efea8fe 100644 --- a/src/test/ui/union/union-suggest-field.rs +++ b/src/test/ui/union/union-suggest-field.rs @@ -9,8 +9,12 @@ impl U { fn main() { let u = U { principle: 0 }; //~^ ERROR union `U` has no field named `principle` + //~| HELP a field with a similar name exists + //~| SUGGESTION principal let w = u.principial; //~ ERROR no field `principial` on type `U` - //~^ did you mean `principal`? + //~| HELP a field with a similar name exists + //~| SUGGESTION principal let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` + //~| HELP maybe a `()` to call it is missing } diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr index 15464eea4c2f3..91d6b30ea0267 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.stderr @@ -2,16 +2,16 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:10:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ field does not exist - did you mean `principal`? + | ^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0609]: no field `principial` on type `U` - --> $DIR/union-suggest-field.rs:12:15 + --> $DIR/union-suggest-field.rs:14:15 | LL | let w = u.principial; //~ ERROR no field `principial` on type `U` - | ^^^^^^^^^^ did you mean `principal`? + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0615]: attempted to take value of method `calculate` on type `U` - --> $DIR/union-suggest-field.rs:15:15 + --> $DIR/union-suggest-field.rs:18:15 | LL | let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` | ^^^^^^^^^ From 4b57fea418c5281c0f71b87793b6621d5cea7030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Mon, 31 Dec 2018 09:44:54 -0800 Subject: [PATCH 082/124] Do not use unicode character in diagnostic help --- src/libsyntax/parse/lexer/mod.rs | 2 +- src/test/ui/parser/issue-23620-invalid-escapes.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index fb46f7a08b935..ecb34e43c590c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -971,7 +971,7 @@ impl<'a> StringReader<'a> { } else { err.span_help( span, - "format of unicode escape sequences is `\\u{…}`", + "format of unicode escape sequences is `\\u{...}`", ); } err.emit(); diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index 025b392627d0f..f6e476ab0cd1d 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -16,7 +16,7 @@ error: incorrect unicode escape sequence LL | let _ = b'/u'; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:10:15 | LL | let _ = b'/u'; @@ -82,7 +82,7 @@ error: incorrect unicode escape sequence LL | let _ = b"/u{a4a4} /xf /u"; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:28:28 | LL | let _ = b"/u{a4a4} /xf /u"; @@ -112,7 +112,7 @@ error: incorrect unicode escape sequence LL | let _ = "/xf /u"; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:34:18 | LL | let _ = "/xf /u"; From 3d0bcd28e2cb27829e1ae22efadb03fcc61b76ae Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sun, 16 Dec 2018 16:18:45 +0300 Subject: [PATCH 083/124] privacy: Use common `DefId` visiting infra for all privacy visitors --- src/librustc/hir/mod.rs | 9 + src/librustc_privacy/lib.rs | 911 ++++++++---------- src/libstd/sys/windows/handle.rs | 5 - src/libstd/sys/windows/stdio.rs | 5 - src/test/ui/error-codes/E0445.rs | 3 - src/test/ui/error-codes/E0445.stderr | 4 +- src/test/ui/impl-trait/issue-49376.rs | 4 +- src/test/ui/issues/issue-18389.stderr | 3 + .../ui/privacy/private-in-public-expr-pat.rs | 13 + .../private-in-public-non-principal-2.rs | 13 + .../private-in-public-non-principal-2.stderr | 8 + .../private-in-public-non-principal.rs | 20 + .../private-in-public-non-principal.stderr | 24 + src/test/ui/privacy/private-in-public-warn.rs | 9 + .../ui/privacy/private-in-public-warn.stderr | 21 +- src/test/ui/privacy/private-in-public.rs | 4 +- src/test/ui/privacy/private-in-public.stderr | 42 +- 17 files changed, 565 insertions(+), 533 deletions(-) create mode 100644 src/test/ui/privacy/private-in-public-expr-pat.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal-2.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal-2.stderr create mode 100644 src/test/ui/privacy/private-in-public-non-principal.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e6fa079207e59..7e87171a5edf7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2090,6 +2090,15 @@ impl VisibilityKind { VisibilityKind::Restricted { .. } => true, } } + + pub fn descr(&self) -> &'static str { + match *self { + VisibilityKind::Public => "public", + VisibilityKind::Inherited => "private", + VisibilityKind::Crate(..) => "crate-visible", + VisibilityKind::Restricted { .. } => "restricted", + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 67b6b2d04506d..0cd8c9da57e29 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -20,22 +20,260 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind}; +use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; -use rustc::ty::subst::UnpackedKind; use rustc::util::nodemap::NodeSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax::ast::{self, CRATE_NODE_ID, Ident}; +use syntax::attr; use syntax::symbol::keywords; use syntax_pos::Span; -use std::cmp; +use std::{cmp, fmt}; use std::mem::replace; +use std::marker::PhantomData; mod diagnostics; +//////////////////////////////////////////////////////////////////////////////// +/// Generic infrastructure used to implement specific visitors below. +//////////////////////////////////////////////////////////////////////////////// + +/// Implemented to visit all `DefId`s in a type. +/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. +trait DefIdVisitor<'a, 'tcx: 'a> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; + fn recurse_into_assoc_tys(&self) -> bool { true } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool; + + /// Not overridden, but used to actually visit types and traits. + fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'a, 'tcx, Self> { + DefIdVisitorSkeleton { + def_id_visitor: self, + visited_opaque_tys: Default::default(), + dummy: Default::default(), + } + } + fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool { + ty_fragment.visit_with(&mut self.skeleton()) + } + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + self.skeleton().visit_trait(trait_ref) + } + fn visit_predicates(&mut self, predicates: Lrc<ty::GenericPredicates<'tcx>>) -> bool { + self.skeleton().visit_predicates(predicates) + } +} + +struct DefIdVisitorSkeleton<'v, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + def_id_visitor: &'v mut V, + visited_opaque_tys: FxHashSet<DefId>, + dummy: PhantomData<TyCtxt<'a, 'tcx, 'tcx>>, +} + +impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + self.def_id_visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref) || + trait_ref.visit_with(self) + } + + fn visit_predicates(&mut self, predicates: Lrc<ty::GenericPredicates<'tcx>>) -> bool { + for (predicate, _) in &predicates.predicates { + let trait_ref = match predicate { + ty::Predicate::Trait(poly_predicate) => { + poly_predicate.skip_binder().trait_ref + } + ty::Predicate::Projection(poly_predicate) => { + if poly_predicate.skip_binder().ty.visit_with(self) { + return true; + } + poly_predicate.skip_binder().projection_ty.trait_ref(self.def_id_visitor.tcx()) + } + ty::Predicate::TypeOutlives(poly_predicate) => { + if poly_predicate.skip_binder().0.visit_with(self) { + return true; + } + continue; + } + ty::Predicate::RegionOutlives(..) => continue, + _ => bug!("unexpected predicate: {:?}", predicate), + }; + if self.visit_trait(trait_ref) { + return true; + } + } + false + } +} + +impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + let tcx = self.def_id_visitor.tcx(); + match ty.sty { + ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | + ty::Foreign(def_id) | + ty::FnDef(def_id, ..) | + ty::Closure(def_id, ..) | + ty::Generator(def_id, ..) => { + if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + return true; + } + // Default type visitor doesn't visit fn signatures. + if let ty::FnDef(..) = ty.sty { + if tcx.fn_sig(def_id).visit_with(self) { + return true; + } + } + // Inherent static methods don't have self type in substs, + // we have to check it additionally. + if let Some(assoc_item) = tcx.opt_associated_item(def_id) { + if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if tcx.type_of(impl_def_id).visit_with(self) { + return true; + } + } + } + } + ty::Projection(proj) | ty::UnnormalizedProjection(proj) => { + if !self.def_id_visitor.recurse_into_assoc_tys() { + // Visitors searching for minimal visibility/reachability want to + // conservatively approximate associated types like `<Type as Trait>::Alias` + // as visible/reachable even if both `Type` and `Trait` are private. + // Ideally, associated types should be substituted in the same way as + // free type aliases, but this isn't done yet. + return false; + } + // This will also visit substs, so we don't need to recurse. + return self.visit_trait(proj.trait_ref(tcx)); + } + ty::Dynamic(predicates, ..) => { + for predicate in *predicates.skip_binder() { + let def_id = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, + ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx).def_id, + ty::ExistentialPredicate::AutoTrait(def_id) => def_id, + }; + if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + return true; + } + } + } + ty::Opaque(def_id, ..) => { + // Skip repeated `Opaque`s to avoid infinite recursion. + if self.visited_opaque_tys.insert(def_id) { + if self.visit_predicates(tcx.predicates_of(def_id)) { + return true; + } + } + } + // These types don't have their own def-ids (but may have subcomponents + // with def-ids that should be visited recursively). + ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | + ty::Float(..) | ty::Str | ty::Never | + ty::Array(..) | ty::Slice(..) | ty::Tuple(..) | + ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) | + ty::Param(..) | ty::Error | ty::GeneratorWitness(..) => {} + ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => + bug!("unexpected type: {:?}", ty), + } + + ty.super_visit_with(self) + } +} + +fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> (ty::Visibility, Span, &'static str) { + match tcx.hir().as_local_node_id(def_id) { + Some(node_id) => { + let vis = match tcx.hir().get(node_id) { + Node::Item(item) => &item.vis, + Node::ForeignItem(foreign_item) => &foreign_item.vis, + Node::TraitItem(..) | Node::Variant(..) => { + return def_id_visibility(tcx, tcx.hir().get_parent_did(node_id)); + } + Node::ImplItem(impl_item) => { + match tcx.hir().get(tcx.hir().get_parent(node_id)) { + Node::Item(item) => match &item.node { + hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis, + hir::ItemKind::Impl(.., Some(trait_ref), _, _) + => return def_id_visibility(tcx, trait_ref.path.def.def_id()), + kind => bug!("unexpected item kind: {:?}", kind), + } + node => bug!("unexpected node kind: {:?}", node), + } + } + Node::StructCtor(vdata) => { + let struct_node_id = tcx.hir().get_parent(node_id); + let item = match tcx.hir().get(struct_node_id) { + Node::Item(item) => item, + node => bug!("unexpected node kind: {:?}", node), + }; + let (mut ctor_vis, mut span, mut descr) = + (ty::Visibility::from_hir(&item.vis, struct_node_id, tcx), + item.vis.span, item.vis.node.descr()); + for field in vdata.fields() { + let field_vis = ty::Visibility::from_hir(&field.vis, node_id, tcx); + if ctor_vis.is_at_least(field_vis, tcx) { + ctor_vis = field_vis; + span = field.vis.span; + descr = field.vis.node.descr(); + } + } + + // If the structure is marked as non_exhaustive then lower the + // visibility to within the crate. + if ctor_vis == ty::Visibility::Public { + let adt_def = tcx.adt_def(tcx.hir().get_parent_did(node_id)); + if adt_def.non_enum_variant().is_field_list_non_exhaustive() { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span; + descr = "crate-visible"; + } + } + + return (ctor_vis, span, descr); + } + Node::Expr(expr) => { + return (ty::Visibility::Restricted(tcx.hir().get_module_parent(expr.id)), + expr.span, "private") + } + node => bug!("unexpected node kind: {:?}", node) + }; + (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr()) + } + None => (tcx.visibility(def_id), tcx.def_span(def_id), "private"), + } +} + +// Set the correct `TypeckTables` for the given `item_id` (or an empty table if +// there is no `TypeckTables` for the item). +fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + tables: &mut &'a ty::TypeckTables<'tcx>, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir().local_def_id(item_id); + + if tcx.has_typeck_tables(def_id) { + replace(tables, tcx.typeck_tables_of(def_id)) + } else { + replace(tables, empty_tables) + } +} + +fn min<'a, 'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::Visibility { + if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } +} + //////////////////////////////////////////////////////////////////////////////// /// Visitor used to determine if pub(restricted) is used anywhere in the crate. /// @@ -56,6 +294,57 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { } } +//////////////////////////////////////////////////////////////////////////////// +/// Visitor used to determine impl visibility and reachability. +//////////////////////////////////////////////////////////////////////////////// + +struct FindMin<'a, 'tcx, M: Min> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels, + min: M, +} + +trait Min: Sized { + const MAX: Self; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self; +} +impl Min for ty::Visibility { + const MAX: Self = ty::Visibility::Public; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx) + } +} +impl Min for Option<AccessLevel> { + const MAX: Self = Some(AccessLevel::Public); + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + cmp::min(if let Some(node_id) = find.tcx.hir().as_local_node_id(def_id) { + find.access_levels.map.get(&node_id).cloned() + } else { + Self::MAX + }, find.min) + } +} + +impl<'a, 'tcx, M: Min> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, M> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn recurse_into_assoc_tys(&self) -> bool { false } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + self.min = M::new_min(self, def_id); + false + } +} + +fn impl_min<'a, 'tcx, M: Min>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, + node_id: ast::NodeId) -> M { + let mut find = FindMin { tcx, access_levels, min: M::MAX }; + let def_id = tcx.hir().local_def_id(node_id); + find.visit(tcx.type_of(def_id)); + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + find.visit_trait(trait_ref); + } + find.min +} + //////////////////////////////////////////////////////////////////////////////// /// The embargo visitor, used to determine the exports of the ast //////////////////////////////////////////////////////////////////////////////// @@ -78,30 +367,6 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { } impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { - fn item_ty_level(&self, item_def_id: DefId) -> Option<AccessLevel> { - let ty_def_id = match self.tcx.type_of(item_def_id).sty { - ty::Adt(adt, _) => adt.did, - ty::Foreign(did) => did, - ty::Dynamic(ref obj, ..) => obj.principal().def_id(), - ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id, - _ => return Some(AccessLevel::Public) - }; - if let Some(node_id) = self.tcx.hir().as_local_node_id(ty_def_id) { - self.get(node_id) - } else { - Some(AccessLevel::Public) - } - } - - fn impl_trait_level(&self, impl_def_id: DefId) -> Option<AccessLevel> { - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) { - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - return self.get(node_id); - } - } - Some(AccessLevel::Public) - } - fn get(&self, id: ast::NodeId) -> Option<AccessLevel> { self.access_levels.map.get(&id).cloned() } @@ -119,10 +384,10 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { } } - fn reach<'b>(&'b mut self, item_id: ast::NodeId) - -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { + fn reach(&mut self, item_id: ast::NodeId, access_level: Option<AccessLevel>) + -> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { - access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), + access_level: cmp::min(access_level, Some(AccessLevel::Reachable)), item_def_id: self.tcx.hir().local_def_id(item_id), ev: self, } @@ -138,15 +403,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { - // Impls inherit level from their types and traits. - hir::ItemKind::Impl(..) => { - let def_id = self.tcx.hir().local_def_id(item.id); - cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id)) - } + hir::ItemKind::Impl(..) => + impl_min::<Option<AccessLevel>>(self.tcx, &self.access_levels, item.id), // Foreign modules inherit level from parents. - hir::ItemKind::ForeignMod(..) => { - self.prev_level - } + hir::ItemKind::ForeignMod(..) => self.prev_level, // Other `pub` items inherit levels from parents. hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | @@ -171,18 +431,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { - if impl_item_ref.vis.node.is_pub() { + if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() { self.update(impl_item_ref.id.node_id, item_level); } } } - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - for impl_item_ref in impl_item_refs { - self.update(impl_item_ref.id.node_id, item_level); - } - } hir::ItemKind::Trait(.., ref trait_item_refs) => { for trait_item_ref in trait_item_refs { self.update(trait_item_ref.id.node_id, item_level); @@ -205,15 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - // Impl trait return types mark their parent function. - // It (and its children) are revisited if the change applies. - hir::ItemKind::Existential(ref ty_data) => { - if let Some(impl_trait_fn) = ty_data.impl_trait_fn { - if let Some(node_id) = self.tcx.hir().as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); - } - } - } + hir::ItemKind::Existential(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -225,10 +472,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } - // Store this node's access level here to propagate the correct - // reachability level through interfaces and children. - let orig_level = replace(&mut self.prev_level, item_level); - // Mark all items in interfaces of reachable items as reachable. match item.node { // The interface is empty. @@ -239,26 +482,26 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - if item_level.is_some() { - // Reach the (potentially private) type and the API being exposed. - self.reach(item.id).ty().predicates(); - } + hir::ItemKind::Existential(..) => { + // FIXME: This is some serious pessimization intended to workaround deficiencies + // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time + // reachable if they are returned via `impl Trait`, even from private functions. + let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); + self.reach(item.id, exist_level).generics().predicates().ty(); } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | - hir::ItemKind::Existential(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().ty(); + self.reach(item.id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., ref trait_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { - let mut reach = self.reach(trait_item_ref.id.node_id); + let mut reach = self.reach(trait_item_ref.id.node_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == hir::AssociatedItemKind::Type && @@ -272,18 +515,19 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } } // Visit everything except for private impl items. - hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref impl_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().impl_trait_ref(); + self.reach(item.id, item_level).generics().predicates(); for impl_item_ref in impl_item_refs { - let id = impl_item_ref.id.node_id; - if trait_ref.is_some() || self.get(id).is_some() { - self.reach(id).generics().predicates().ty(); + let impl_item_level = self.get(impl_item_ref.id.node_id); + if impl_item_level.is_some() { + self.reach(impl_item_ref.id.node_id, impl_item_level) + .generics().predicates().ty(); } } } @@ -292,24 +536,27 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } for variant in &def.variants { - if self.get(variant.node.data.id()).is_some() { + let variant_level = self.get(variant.node.data.id()); + if variant_level.is_some() { for field in variant.node.data.fields() { - self.reach(field.id).ty(); + self.reach(field.id, variant_level).ty(); } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.update(item.id, Some(AccessLevel::Reachable)); + self.update(item.id, variant_level); } } } // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod(ref foreign_mod) => { for foreign_item in &foreign_mod.items { - if self.get(foreign_item.id).is_some() { - self.reach(foreign_item.id).generics().predicates().ty(); + let foreign_item_level = self.get(foreign_item.id); + if foreign_item_level.is_some() { + self.reach(foreign_item.id, foreign_item_level) + .generics().predicates().ty(); } } } @@ -317,29 +564,28 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for field in struct_def.fields() { - if self.get(field.id).is_some() { - self.reach(field.id).ty(); + let field_level = self.get(field.id); + if field_level.is_some() { + self.reach(field.id, field_level).ty(); } } } } } + let orig_level = replace(&mut self.prev_level, item_level); intravisit::walk_item(self, item); - self.prev_level = orig_level; } fn visit_block(&mut self, b: &'tcx hir::Block) { - let orig_level = replace(&mut self.prev_level, None); - // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, // constant, type, field, etc., in which this block resides. + let orig_level = replace(&mut self.prev_level, None); intravisit::walk_block(self, b); - self.prev_level = orig_level; } @@ -410,13 +656,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } -impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { +impl<'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.ev.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.ev.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -426,73 +672,23 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - let predicates = self.ev.tcx.predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.ev.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.ev.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.ev.tcx.fn_sig(def_id).visit_with(self); - } - } - self - } - - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } + self.visit(self.ev.tcx.type_of(self.item_def_id)); self } - - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir().expect_item(node_id); - self.ev.update(item.id, self.access_level); - } - } } -impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => Some(proj.item_def_id), - ty::FnDef(def_id, ..) | - ty::Closure(def_id, ..) | - ty::Generator(def_id, ..) | - ty::Opaque(def_id, _) => Some(def_id), - _ => None - }; - - if let Some(def_id) = ty_def_id { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { - self.ev.update(node_id, self.access_level); - } +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.ev.tcx } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { + self.ev.update(node_id, self.access_level); } - - ty.super_visit_with(self) + false } } @@ -528,22 +724,6 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -// Set the correct `TypeckTables` for the given `item_id` (or an empty table if -// there is no `TypeckTables` for the item). -fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - tables: &mut &'a ty::TypeckTables<'tcx>, - empty_tables: &'a ty::TypeckTables<'tcx>) - -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(item_id); - - if tcx.has_typeck_tables(def_id) { - replace(tables, tcx.typeck_tables_of(def_id)) - } else { - replace(tables, empty_tables) - } -} - impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. @@ -644,73 +824,22 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { in_body: bool, span: Span, empty_tables: &'a ty::TypeckTables<'tcx>, - visited_opaque_tys: FxHashSet<DefId> } impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { - fn def_id_visibility(&self, did: DefId) -> ty::Visibility { - match self.tcx.hir().as_local_node_id(did) { - Some(node_id) => { - let vis = match self.tcx.hir().get(node_id) { - Node::Item(item) => &item.vis, - Node::ForeignItem(foreign_item) => &foreign_item.vis, - Node::ImplItem(impl_item) => &impl_item.vis, - Node::TraitItem(..) | - Node::Variant(..) => { - return self.def_id_visibility(self.tcx.hir().get_parent_did(node_id)); - } - Node::StructCtor(vdata) => { - let struct_node_id = self.tcx.hir().get_parent(node_id); - let struct_vis = match self.tcx.hir().get(struct_node_id) { - Node::Item(item) => &item.vis, - node => bug!("unexpected node kind: {:?}", node), - }; - let mut ctor_vis - = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx); - for field in vdata.fields() { - let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx); - if ctor_vis.is_at_least(field_vis, self.tcx) { - ctor_vis = field_vis; - } - } - - // If the structure is marked as non_exhaustive then lower the - // visibility to within the crate. - let struct_def_id = self.tcx.hir().get_parent_did(node_id); - let adt_def = self.tcx.adt_def(struct_def_id); - if adt_def.non_enum_variant().is_field_list_non_exhaustive() - && ctor_vis == ty::Visibility::Public - { - ctor_vis = ty::Visibility::Restricted( - DefId::local(CRATE_DEF_INDEX)); - } - - return ctor_vis; - } - node => bug!("unexpected node kind: {:?}", node) - }; - ty::Visibility::from_hir(vis, node_id, self.tcx) - } - None => self.tcx.visibility(did), - } - } - fn item_is_accessible(&self, did: DefId) -> bool { - self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx) + def_id_visibility(self.tcx, did).0.is_accessible_from(self.current_item, self.tcx) } // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - if self.tables.node_id_to_type(id).visit_with(self) { - return true; - } - if self.tables.node_substs(id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(id)) || self.visit(self.tables.node_substs(id)) { return true; } if let Some(adjustments) = self.tables.adjustments().get(id) { for adjustment in adjustments { - if adjustment.target.visit_with(self) { + if self.visit(adjustment.target) { return true; } } @@ -718,14 +847,12 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { false } - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + let is_error = !self.item_is_accessible(def_id); + if is_error { + self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr)); } - - trait_ref.super_visit_with(self) + is_error } } @@ -749,14 +876,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { self.span = hir_ty.span; if self.in_body { // Types in bodies. - if self.tables.node_id_to_type(hir_ty.hir_id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(hir_ty.hir_id)) { return; } } else { // Types in signatures. // FIXME: This is very ineffective. Ideally each HIR type should be converted // into a semantic type only once and the result should be cached somehow. - if rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) { + if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) { return; } } @@ -771,12 +898,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // The traits' privacy in bodies is already checked as a part of trait object types. let (principal, projections) = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); - if self.check_trait_ref(*principal.skip_binder()) { + if self.visit_trait(*principal.skip_binder()) { return; } for (poly_predicate, _) in projections { let tcx = self.tcx; - if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { + if self.visit(poly_predicate.skip_binder().ty) || + self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { return; } } @@ -802,8 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Method calls have to be checked specially. self.span = span; if let Some(def) = self.tables.type_dependent_defs().get(expr.hir_id) { - let def_id = def.def_id(); - if self.tcx.type_of(def_id).visit_with(self) { + if self.visit(self.tcx.type_of(def.def_id())) { return; } } else { @@ -827,7 +954,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { let def = match *qpath { hir::QPath::Resolved(_, ref path) => match path.def { Def::Method(..) | Def::AssociatedConst(..) | - Def::AssociatedTy(..) | Def::Static(..) => Some(path.def), + Def::AssociatedTy(..) | Def::AssociatedExistential(..) | + Def::Static(..) => Some(path.def), _ => None, } hir::QPath::TypeRelative(..) => { @@ -874,13 +1002,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = self.current_item; - let orig_tables = update_tables(self.tcx, - item.id, - &mut self.tables, - self.empty_tables); + let orig_current_item = + replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); let orig_in_body = replace(&mut self.in_body, false); - self.current_item = self.tcx.hir().local_def_id(item.id); + let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -900,96 +1025,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | - ty::FnDef(def_id, ..) | - ty::Foreign(def_id) => { - if !self.item_is_accessible(def_id) { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - if let ty::FnDef(..) = ty.sty { - if self.tcx.fn_sig(def_id).visit_with(self) { - return true; - } - } - // Inherent static methods don't have self type in substs, - // we have to check it additionally. - if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { - if let ty::ImplContainer(impl_def_id) = assoc_item.container { - if self.tcx.type_of(impl_def_id).visit_with(self) { - return true; - } - } - } - } - ty::Dynamic(ref predicates, ..) => { - let is_private = predicates.skip_binder().iter().any(|predicate| { - let def_id = match *predicate { - ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => - proj.trait_ref(self.tcx).def_id, - ty::ExistentialPredicate::AutoTrait(def_id) => def_id, - }; - !self.item_is_accessible(def_id) - }); - if is_private { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - } - ty::Projection(ref proj) => { - let tcx = self.tcx; - if self.check_trait_ref(proj.trait_ref(tcx)) { - return true; - } - } - ty::Opaque(def_id, ..) => { - for (predicate, _) in &self.tcx.predicates_of(def_id).predicates { - let trait_ref = match *predicate { - ty::Predicate::Trait(ref poly_trait_predicate) => { - Some(poly_trait_predicate.skip_binder().trait_ref) - } - ty::Predicate::Projection(ref poly_projection_predicate) => { - if poly_projection_predicate.skip_binder().ty.visit_with(self) { - return true; - } - Some(poly_projection_predicate.skip_binder() - .projection_ty.trait_ref(self.tcx)) - } - ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => None, - _ => bug!("unexpected predicate: {:?}", predicate), - }; - if let Some(trait_ref) = trait_ref { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - for subst in trait_ref.substs.iter() { - // Skip repeated `Opaque`s to avoid infinite recursion. - if let UnpackedKind::Type(ty) = subst.unpack() { - if let ty::Opaque(def_id, ..) = ty.sty { - if !self.visited_opaque_tys.insert(def_id) { - continue; - } - } - } - if subst.visit_with(self) { - return true; - } - } - } - } - } - _ => {} - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for TypePrivacyVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1283,13 +1322,13 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } for predicate in &generics.where_clause.predicates { match predicate { - &hir::WherePredicate::BoundPredicate(ref bound_pred) => { + hir::WherePredicate::BoundPredicate(bound_pred) => { for bound in bound_pred.bounds.iter() { self.check_generic_bound(bound) } } - &hir::WherePredicate::RegionPredicate(_) => {} - &hir::WherePredicate::EqPredicate(ref eq_pred) => { + hir::WherePredicate::RegionPredicate(_) => {} + hir::WherePredicate::EqPredicate(eq_pred) => { self.visit_ty(&eq_pred.rhs_ty); } } @@ -1349,8 +1388,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> { span: Span, /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, - /// The visibility of the least visible component that has been visited. - min_visibility: ty::Visibility, has_pub_restricted: bool, has_old_errors: bool, in_assoc_ty: bool, @@ -1362,7 +1399,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -1378,132 +1415,47 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { // consider the ones that the user wrote. This is important // for the inferred outlives rules; see // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`. - let predicates = self.tcx.explicit_predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.tcx.fn_sig(def_id).visit_with(self); - } - } + self.visit(self.tcx.type_of(self.item_def_id)); self } - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } - self - } + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + let node_id = match self.tcx.hir().as_local_node_id(def_id) { + Some(node_id) => node_id, + None => return false, + }; - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir().expect_item(node_id); - let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - struct_span_err!(self.tcx.sess, self.span, E0445, - "private trait `{}` in public interface", trait_ref) - .span_label(self.span, format!( - "can't leak private trait")) - .emit(); + let (vis, vis_span, vis_descr) = def_id_visibility(self.tcx, def_id); + if !vis.is_at_least(self.required_visibility, self.tcx) { + let msg = format!("{} {} `{}` in public interface", vis_descr, kind, descr); + if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { + let mut err = if kind == "trait" { + struct_span_err!(self.tcx.sess, self.span, E0445, "{}", msg) } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); - } + struct_span_err!(self.tcx.sess, self.span, E0446, "{}", msg) + }; + err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind)); + err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr)); + err.emit(); + } else { + let err_code = if kind == "trait" { "E0445" } else { "E0446" }; + self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span, + &format!("{} (error {})", msg, err_code)); } } + false } } -impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => { - if self.required_visibility == ty::Visibility::Invisible { - // Conservatively approximate the whole type alias as public without - // recursing into its components when determining impl publicity. - // For example, `impl <Type as Trait>::Alias {...}` may be a public impl - // even if both `Type` and `Trait` are private. - // Ideally, associated types should be substituted in the same way as - // free type aliases, but this isn't done yet. - return false; - } - let trait_ref = proj.trait_ref(self.tcx); - Some(trait_ref.def_id) - } - _ => None - }; - - if let Some(def_id) = ty_def_id { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - let hir_vis = match self.tcx.hir().find(node_id) { - Some(Node::Item(item)) => &item.vis, - Some(Node::ForeignItem(item)) => &item.vis, - _ => bug!("expected item of foreign item"), - }; - - let vis = ty::Visibility::from_hir(hir_vis, node_id, self.tcx); - - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - let vis_adj = match hir_vis.node { - hir::VisibilityKind::Crate(_) => "crate-visible", - hir::VisibilityKind::Restricted { .. } => "restricted", - _ => "private" - }; - - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - let mut err = struct_span_err!(self.tcx.sess, self.span, E0446, - "{} type `{}` in public interface", vis_adj, ty); - err.span_label(self.span, format!("can't leak {} type", vis_adj)); - err.span_label(hir_vis.span, format!("`{}` declared as {}", ty, vis_adj)); - err.emit(); - } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("{} type `{}` in public \ - interface (error E0446)", vis_adj, ty)); - } - } - } - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1511,7 +1463,6 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, has_pub_restricted: bool, old_error_set: &'a NodeSet, - inner_visibility: ty::Visibility, } impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { @@ -1544,7 +1495,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { tcx: self.tcx, item_def_id: self.tcx.hir().local_def_id(item_id), span: self.tcx.hir().span(item_id), - min_visibility: ty::Visibility::Public, required_visibility, has_pub_restricted: self.has_pub_restricted, has_old_errors, @@ -1560,10 +1510,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> fn visit_item(&mut self, item: &'tcx hir::Item) { let tcx = self.tcx; - let min = |vis1: ty::Visibility, vis2| { - if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } - }; - let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx); match item.node { @@ -1575,23 +1521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemKind::Use(..) => {} // No subitems. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - // Check the traits being exposed, as they're separate, - // e.g., `impl Iterator<Item=T>` has two predicates, - // `X: Iterator` and `<X as Iterator>::Item == T`, - // where `X` is the `impl Iterator<Item=T>` itself, - // stored in `predicates_of`, not in the `Ty` itself. - self.check(item.id, item_visibility).predicates(); - } // Subitems of these items have inherited publicity. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Ty(..) => { + hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { self.check(item.id, item_visibility).generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = item_visibility; - intravisit::walk_item(self, item); } hir::ItemKind::Trait(.., ref trait_item_refs) => { self.check(item.id, item_visibility).generics().predicates(); @@ -1635,56 +1568,30 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> for field in struct_def.fields() { let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx); - self.check(field.id, min(item_visibility, field_visibility)).ty(); + self.check(field.id, min(item_visibility, field_visibility, tcx)).ty(); } } // An inherent impl is public when its type is public // Subitems of inherent impls have their own publicity. - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { - let ty_vis = - self.check(item.id, ty::Visibility::Invisible).ty().min_visibility; - self.check(item.id, ty_vis).generics().predicates(); - - for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx); - let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis)); - check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; - check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = impl_item_vis; - intravisit::walk_impl_item(self, impl_item); - } - } // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - let vis = self.check(item.id, ty::Visibility::Invisible) - .ty().impl_trait_ref().min_visibility; - self.check(item.id, vis).generics().predicates(); + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + let impl_vis = impl_min::<ty::Visibility>(tcx, &Default::default(), item.id); + self.check(item.id, impl_vis).generics().predicates(); for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let mut check = self.check(impl_item.id, vis); + let impl_item = tcx.hir().impl_item(impl_item_ref.id); + let impl_item_vis = if trait_ref.is_none() { + min(ty::Visibility::from_hir(&impl_item.vis, item.id, tcx), impl_vis, tcx) + } else { + impl_vis + }; + let mut check = self.check(impl_item.id, impl_item_vis); check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = vis; - intravisit::walk_impl_item(self, impl_item); } } } } - - fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { - // Handled in `visit_item` above. - } - - // Don't recurse into expressions in array sizes or const initializers. - fn visit_expr(&mut self, _: &'tcx hir::Expr) {} - // Don't recurse into patterns in function arguments. - fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } pub fn provide(providers: &mut Providers) { @@ -1724,7 +1631,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_body: false, span: krate.span, empty_tables: &empty_tables, - visited_opaque_tys: FxHashSet::default() }; intravisit::walk_crate(&mut visitor, krate); @@ -1770,7 +1676,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, has_pub_restricted, old_error_set: &visitor.old_error_set, - inner_visibility: ty::Visibility::Public, }; krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 7d12e0f6ef085..855efbd3eb5d6 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -160,11 +160,6 @@ impl RawHandle { } } - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { - let mut me = self; - (&mut me).read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let mut amt = 0; let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index f331397db8cf3..a4f4bd22cd921 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -128,11 +128,6 @@ impl Stdin { // MemReader shouldn't error here since we just filled it utf8.read(buf) } - - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { - let mut me = self; - (&mut me).read_to_end(buf) - } } #[unstable(reason = "not public", issue = "0", feature = "fd_read")] diff --git a/src/test/ui/error-codes/E0445.rs b/src/test/ui/error-codes/E0445.rs index 570c37ef2ccbe..a9a3aee2500fb 100644 --- a/src/test/ui/error-codes/E0445.rs +++ b/src/test/ui/error-codes/E0445.rs @@ -4,12 +4,9 @@ trait Foo { pub trait Bar : Foo {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub struct Bar2<T: Foo>(pub T); //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub fn foo<T: Foo> (t: T) {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait fn main() {} diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr index 747e4daf74ec2..d0d6ebe16c7f7 100644 --- a/src/test/ui/error-codes/E0445.stderr +++ b/src/test/ui/error-codes/E0445.stderr @@ -5,13 +5,13 @@ LL | pub trait Bar : Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:8:1 + --> $DIR/E0445.rs:7:1 | LL | pub struct Bar2<T: Foo>(pub T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:11:1 + --> $DIR/E0445.rs:9:1 | LL | pub fn foo<T: Foo> (t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issue-49376.rs index 4a45988e45d7f..13671b8dbf448 100644 --- a/src/test/ui/impl-trait/issue-49376.rs +++ b/src/test/ui/impl-trait/issue-49376.rs @@ -9,9 +9,11 @@ fn gen() -> impl PartialOrd + PartialEq + Debug { } struct Bar {} trait Foo<T = Self> {} +trait FooNested<T = Option<Self>> {} impl Foo for Bar {} +impl FooNested for Bar {} -fn foo() -> impl Foo { +fn foo() -> impl Foo + FooNested { Bar {} } diff --git a/src/test/ui/issues/issue-18389.stderr b/src/test/ui/issues/issue-18389.stderr index 9cbe8c05b7e3d..02ff6b6d5bff4 100644 --- a/src/test/ui/issues/issue-18389.stderr +++ b/src/test/ui/issues/issue-18389.stderr @@ -1,6 +1,9 @@ error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface --> $DIR/issue-18389.rs:7:1 | +LL | trait Private<P, R> { + | - `Private<<Self as Public>::P, <Self as Public>::R>` declared as private +... LL | / pub trait Public: Private< LL | | //~^ ERROR private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface LL | | <Self as Public>::P, diff --git a/src/test/ui/privacy/private-in-public-expr-pat.rs b/src/test/ui/privacy/private-in-public-expr-pat.rs new file mode 100644 index 0000000000000..a3e53bdf45de3 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-expr-pat.rs @@ -0,0 +1,13 @@ +// Patterns and expressions are not interface parts and don't produce private-in-public errors. + +// compile-pass + +struct Priv1(usize); +struct Priv2; + +pub struct Pub(Priv2); + +pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK +pub fn public_pat(Pub(Priv2): Pub) {} // OK + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs new file mode 100644 index 0000000000000..95bf24e7b0f8d --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -0,0 +1,13 @@ +#![feature(optin_builtin_traits)] + +#[allow(private_in_public)] +mod m { + pub trait PubPrincipal {} + auto trait PrivNonPrincipal {} + pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } +} + +fn main() { + m::leak_dyn_nonprincipal(); + //~^ ERROR type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private +} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr new file mode 100644 index 0000000000000..e15ca9d6dd410 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -0,0 +1,8 @@ +error: type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private + --> $DIR/private-in-public-non-principal-2.rs:11:5 + | +LL | m::leak_dyn_nonprincipal(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs new file mode 100644 index 0000000000000..df2f224c403ac --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -0,0 +1,20 @@ +#![feature(optin_builtin_traits)] + +pub trait PubPrincipal {} +auto trait PrivNonPrincipal {} + +pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } +//~^ WARN private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface +//~| WARN this was previously accepted + +#[deny(missing_docs)] +fn container() { + impl dyn PubPrincipal { + pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + } + impl dyn PubPrincipal + PrivNonPrincipal { + pub fn check_doc_lint() {} // OK, no missing doc lint + } +} + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr new file mode 100644 index 0000000000000..6c9da53ad3fe0 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -0,0 +1,24 @@ +warning: private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface (error E0446) + --> $DIR/private-in-public-non-principal.rs:6:1 + | +LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(private_in_public)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> + +error: missing documentation for a method + --> $DIR/private-in-public-non-principal.rs:13:9 + | +LL | pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/private-in-public-non-principal.rs:10:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 0da0d03595d83..29f365b69be4d 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -213,6 +213,15 @@ mod aliases_pub { impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias { type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface } + impl PrivUseAliasTr for Option<<Priv as PrivTr>::AssocAlias> { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for (<Priv as PrivTr>::AssocAlias, Priv) { + type Check = Priv; // OK + } + impl PrivUseAliasTr for Option<(<Priv as PrivTr>::AssocAlias, Priv)> { + type Check = Priv; // OK + } } mod aliases_priv { diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index ab9ff8d64d36c..8f9e7cd74f992 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -297,8 +297,17 @@ LL | struct Priv; LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface | ^^^^^^^^^^^^^^^^^^ can't leak private type +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:217:9 + | +LL | struct Priv; + | - `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + | ^^^^^^^^^^^^^^^^^^ can't leak private type + error: private trait `aliases_priv::PrivTr1` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:238:5 + --> $DIR/private-in-public-warn.rs:247:5 | LL | pub trait Tr1: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,8 +315,8 @@ LL | pub trait Tr1: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: private type `aliases_priv::Priv2` in public interface (error E0446) - --> $DIR/private-in-public-warn.rs:241:5 +error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -315,8 +324,8 @@ LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:241:5 +error: private type `aliases_priv::Priv2` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -324,6 +333,6 @@ LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0446`. diff --git a/src/test/ui/privacy/private-in-public.rs b/src/test/ui/privacy/private-in-public.rs index 288298cfbfcf6..08c00f44f2269 100644 --- a/src/test/ui/privacy/private-in-public.rs +++ b/src/test/ui/privacy/private-in-public.rs @@ -102,7 +102,7 @@ mod aliases_pub { // This should be OK, but associated type aliases are not substituted yet pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - //~^ ERROR private type `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` in public interface + //~^ ERROR private trait `aliases_pub::PrivTr` in public interface //~| ERROR private type `aliases_pub::Priv` in public interface impl PrivUseAlias { @@ -131,7 +131,7 @@ mod aliases_priv { pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `aliases_priv::Priv1` in public interface pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - //~^ ERROR private type `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` in public + //~^ ERROR private trait `aliases_priv::PrivTr` in public interface //~| ERROR private type `aliases_priv::Priv` in public interface } diff --git a/src/test/ui/privacy/private-in-public.stderr b/src/test/ui/privacy/private-in-public.stderr index 2bd7503ab5aae..bf88a83e633cc 100644 --- a/src/test/ui/privacy/private-in-public.stderr +++ b/src/test/ui/privacy/private-in-public.stderr @@ -82,24 +82,36 @@ LL | pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Pri error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:31:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub enum E<T: PrivTr> { V(T) } //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:32:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:33:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub struct S1<T: PrivTr>(T); //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:34:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | / impl<T: PrivTr> Pub<T> { //~ ERROR private trait `traits::PrivTr` in public interface LL | | pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface LL | | } @@ -108,30 +120,45 @@ LL | | } error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:35:9 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:44:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub enum E<T> where T: PrivTr { V(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:46:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f<T>(arg: T) where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:48:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub struct S1<T>(T) where T: PrivTr; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:50:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | / impl<T> Pub<T> where T: PrivTr { LL | | //~^ ERROR private trait `traits_where::PrivTr` in public interface LL | | pub fn f<U>(arg: U) where U: PrivTr {} @@ -142,6 +169,9 @@ LL | | } error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:52:9 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f<U>(arg: U) where U: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait @@ -181,14 +211,14 @@ LL | struct Priv; LL | pub fn f(arg: Priv) {} //~ ERROR private type `impls::Priv` in public interface | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` in public interface +error[E0445]: private trait `aliases_pub::PrivTr` in public interface --> $DIR/private-in-public.rs:104:5 | LL | trait PrivTr { - | - `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` declared as private + | - `aliases_pub::PrivTr` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public.rs:104:5 @@ -226,14 +256,14 @@ LL | struct Priv2; LL | pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` in public interface +error[E0445]: private trait `aliases_priv::PrivTr` in public interface --> $DIR/private-in-public.rs:133:5 | LL | trait PrivTr { - | - `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` declared as private + | - `aliases_priv::PrivTr` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_priv::Priv` in public interface --> $DIR/private-in-public.rs:133:5 From e4bab0e81aacc00647e0748d8319a729c4da28a8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Mon, 31 Dec 2018 03:02:40 +0300 Subject: [PATCH 084/124] Address review comments Say "trait" instead of "type" in diagnostics for `dyn Trait` --- src/librustc/util/ppaux.rs | 3 + src/librustc_privacy/lib.rs | 181 ++++++++++-------- .../associated-item-privacy-type-binding.rs | 12 +- ...ssociated-item-privacy-type-binding.stderr | 12 +- .../private-in-public-non-principal-2.rs | 2 +- .../private-in-public-non-principal-2.stderr | 2 +- .../private-in-public-non-principal.rs | 2 +- .../private-in-public-non-principal.stderr | 2 +- src/test/ui/privacy/private-inferred-type.rs | 2 +- .../ui/privacy/private-inferred-type.stderr | 4 +- 10 files changed, 126 insertions(+), 96 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d5e6bb9a2e2a5..318d7adb19011 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -709,6 +709,9 @@ define_print! { define_print! { ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { + display { + cx.parameterized(f, self.substs, self.def_id, &[]) + } debug { ty::tls::with(|tcx| { let dummy_self = tcx.mk_infer(ty::FreshTy(0)); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0cd8c9da57e29..c6626c1551f4a 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -23,6 +23,7 @@ use rustc::middle::privacy::{AccessLevel, AccessLevels}; use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; +use rustc::ty::subst::Substs; use rustc::util::nodemap::NodeSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -31,8 +32,7 @@ use syntax::attr; use syntax::symbol::keywords; use syntax_pos::Span; -use std::{cmp, fmt}; -use std::mem::replace; +use std::{cmp, fmt, mem}; use std::marker::PhantomData; mod diagnostics; @@ -43,6 +43,12 @@ mod diagnostics; /// Implemented to visit all `DefId`s in a type. /// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. +/// The idea is to visit "all components of a type", as documented in +/// https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type +/// Default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings. +/// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait def-ids +/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits +/// in `impl Trait`, see individual commits in `DefIdVisitorSkeleton::visit_ty`. trait DefIdVisitor<'a, 'tcx: 'a> { fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; fn recurse_into_assoc_tys(&self) -> bool { true } @@ -79,33 +85,38 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> where V: DefIdVisitor<'a, 'tcx> + ?Sized { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { - self.def_id_visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref) || - trait_ref.visit_with(self) + let TraitRef { def_id, substs } = trait_ref; + self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || substs.visit_with(self) } fn visit_predicates(&mut self, predicates: Lrc<ty::GenericPredicates<'tcx>>) -> bool { - for (predicate, _) in &predicates.predicates { - let trait_ref = match predicate { + let ty::GenericPredicates { parent: _, predicates } = &*predicates; + for (predicate, _span) in predicates { + match predicate { ty::Predicate::Trait(poly_predicate) => { - poly_predicate.skip_binder().trait_ref + let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); + if self.visit_trait(trait_ref) { + return true; + } } ty::Predicate::Projection(poly_predicate) => { - if poly_predicate.skip_binder().ty.visit_with(self) { + let ty::ProjectionPredicate { projection_ty, ty } = + *poly_predicate.skip_binder(); + if ty.visit_with(self) { + return true; + } + if self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx())) { return true; } - poly_predicate.skip_binder().projection_ty.trait_ref(self.def_id_visitor.tcx()) } ty::Predicate::TypeOutlives(poly_predicate) => { - if poly_predicate.skip_binder().0.visit_with(self) { + let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); + if ty.visit_with(self) { return true; } - continue; } - ty::Predicate::RegionOutlives(..) => continue, + ty::Predicate::RegionOutlives(..) => {}, _ => bug!("unexpected predicate: {:?}", predicate), - }; - if self.visit_trait(trait_ref) { - return true; } } false @@ -117,6 +128,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let tcx = self.def_id_visitor.tcx(); + // Substs are not visited here because they are visited below in `super_visit_with`. match ty.sty { ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | ty::Foreign(def_id) | @@ -126,14 +138,18 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> if self.def_id_visitor.visit_def_id(def_id, "type", ty) { return true; } - // Default type visitor doesn't visit fn signatures. + // Default type visitor doesn't visit signatures of fn types. + // Something like `fn() -> Priv {my_func}` is considered a private type even if + // `my_func` is public, so we need to visit signatures. if let ty::FnDef(..) = ty.sty { if tcx.fn_sig(def_id).visit_with(self) { return true; } } - // Inherent static methods don't have self type in substs, - // we have to check it additionally. + // Inherent static methods don't have self type in substs. + // Something like `fn() {my_method}` type of the method + // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type, + // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let ty::ImplContainer(impl_def_id) = assoc_item.container { if tcx.type_of(impl_def_id).visit_with(self) { @@ -156,12 +172,14 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> } ty::Dynamic(predicates, ..) => { for predicate in *predicates.skip_binder() { - let def_id = match *predicate { - ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx).def_id, - ty::ExistentialPredicate::AutoTrait(def_id) => def_id, + let trait_ref = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref, + ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx), + ty::ExistentialPredicate::AutoTrait(def_id) => + ty::ExistentialTraitRef { def_id, substs: Substs::empty() }, }; - if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref; + if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) { return true; } } @@ -169,6 +187,9 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> ty::Opaque(def_id, ..) => { // Skip repeated `Opaque`s to avoid infinite recursion. if self.visited_opaque_tys.insert(def_id) { + // Default type visitor doesn't visit traits in `impl Trait`. + // Something like `impl PrivTr` is considered a private type, + // so we need to visit the traits additionally. if self.visit_predicates(tcx.predicates_of(def_id)) { return true; } @@ -249,24 +270,22 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) }; (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr()) } - None => (tcx.visibility(def_id), tcx.def_span(def_id), "private"), + None => { + let vis = tcx.visibility(def_id); + let descr = if vis == ty::Visibility::Public { "public" } else { "private" }; + (vis, tcx.def_span(def_id), descr) + } } } // Set the correct `TypeckTables` for the given `item_id` (or an empty table if // there is no `TypeckTables` for the item). -fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - tables: &mut &'a ty::TypeckTables<'tcx>, - empty_tables: &'a ty::TypeckTables<'tcx>) - -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(item_id); - - if tcx.has_typeck_tables(def_id) { - replace(tables, tcx.typeck_tables_of(def_id)) - } else { - replace(tables, empty_tables) - } +fn item_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + node_id: ast::NodeId, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir().local_def_id(node_id); + if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables } } fn min<'a, 'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -298,23 +317,45 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { /// Visitor used to determine impl visibility and reachability. //////////////////////////////////////////////////////////////////////////////// -struct FindMin<'a, 'tcx, M: Min> { +struct FindMin<'a, 'tcx, VL: VisibilityLike> { tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, - min: M, + min: VL, +} + +impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, VL> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn recurse_into_assoc_tys(&self) -> bool { false } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + self.min = VL::new_min(self, def_id); + false + } } -trait Min: Sized { +trait VisibilityLike: Sized { const MAX: Self; fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self; + + // Returns an over-approximation (`recurse_into_assoc_tys` = false) of visibility due to + // associated types for which we can't determine visibility precisely. + fn of_impl<'a, 'tcx>(node_id: ast::NodeId, tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels) -> Self { + let mut find = FindMin { tcx, access_levels, min: Self::MAX }; + let def_id = tcx.hir().local_def_id(node_id); + find.visit(tcx.type_of(def_id)); + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + find.visit_trait(trait_ref); + } + find.min + } } -impl Min for ty::Visibility { +impl VisibilityLike for ty::Visibility { const MAX: Self = ty::Visibility::Public; fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx) } } -impl Min for Option<AccessLevel> { +impl VisibilityLike for Option<AccessLevel> { const MAX: Self = Some(AccessLevel::Public); fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { cmp::min(if let Some(node_id) = find.tcx.hir().as_local_node_id(def_id) { @@ -325,26 +366,6 @@ impl Min for Option<AccessLevel> { } } -impl<'a, 'tcx, M: Min> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, M> { - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } - fn recurse_into_assoc_tys(&self) -> bool { false } - fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { - self.min = M::new_min(self, def_id); - false - } -} - -fn impl_min<'a, 'tcx, M: Min>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, - node_id: ast::NodeId) -> M { - let mut find = FindMin { tcx, access_levels, min: M::MAX }; - let def_id = tcx.hir().local_def_id(node_id); - find.visit(tcx.type_of(def_id)); - if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - find.visit_trait(trait_ref); - } - find.min -} - //////////////////////////////////////////////////////////////////////////////// /// The embargo visitor, used to determine the exports of the ast //////////////////////////////////////////////////////////////////////////////// @@ -404,7 +425,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { hir::ItemKind::Impl(..) => - impl_min::<Option<AccessLevel>>(self.tcx, &self.access_levels, item.id), + Option::<AccessLevel>::of_impl(item.id, self.tcx, &self.access_levels), // Foreign modules inherit level from parents. hir::ItemKind::ForeignMod(..) => self.prev_level, // Other `pub` items inherit levels from parents. @@ -575,7 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - let orig_level = replace(&mut self.prev_level, item_level); + let orig_level = mem::replace(&mut self.prev_level, item_level); intravisit::walk_item(self, item); self.prev_level = orig_level; } @@ -584,7 +605,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, // constant, type, field, etc., in which this block resides. - let orig_level = replace(&mut self.prev_level, None); + let orig_level = mem::replace(&mut self.prev_level, None); intravisit::walk_block(self, b); self.prev_level = orig_level; } @@ -732,28 +753,31 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; } fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = replace(&mut self.current_item, item.id); - let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); + let orig_current_item = mem::replace(&mut self.current_item, item.id); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.current_item = orig_current_item; self.tables = orig_tables; } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } @@ -864,8 +888,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); - let orig_in_body = replace(&mut self.in_body, true); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_in_body = mem::replace(&mut self.in_body, true); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; @@ -1003,9 +1027,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_current_item = - replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); - let orig_in_body = replace(&mut self.in_body, false); - let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); + mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); + let orig_in_body = mem::replace(&mut self.in_body, false); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -1013,13 +1038,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } @@ -1576,7 +1603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { - let impl_vis = impl_min::<ty::Visibility>(tcx, &Default::default(), item.id); + let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default()); self.check(item.id, impl_vis).generics().predicates(); for impl_item_ref in impl_item_refs { let impl_item = tcx.hir().impl_item(impl_item_ref.id); diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.rs b/src/test/ui/privacy/associated-item-privacy-type-binding.rs index ff274ab8f1f8d..591e9df81eb0b 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.rs @@ -9,19 +9,19 @@ mod priv_trait { pub macro mac1() { let _: Box<PubTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private - //~| ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy2 = Box<PubTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr2: PubTr<AssocTy = u8> {} //~^ ERROR trait `priv_trait::PrivTr` is private } pub macro mac2() { let _: Box<PrivTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private - //~| ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr1: PrivTr<AssocTy = u8> {} //~^ ERROR trait `priv_trait::PrivTr` is private } diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index 331e2f689b547..7f6886d7f9ad4 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -1,4 +1,4 @@ -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | LL | let _: Box<PubTr<AssocTy = u8>>; @@ -7,7 +7,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | LL | let _: Box<PubTr<AssocTy = u8>>; @@ -16,7 +16,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | LL | type InSignatureTy2 = Box<PubTr<AssocTy = u8>>; @@ -34,7 +34,7 @@ LL | trait InSignatureTr2: PubTr<AssocTy = u8> {} LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | LL | let _: Box<PrivTr<AssocTy = u8>>; @@ -43,7 +43,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | LL | let _: Box<PrivTr<AssocTy = u8>>; @@ -52,7 +52,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | LL | type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>; diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs index 95bf24e7b0f8d..02fd92aa7a4ef 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.rs +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -9,5 +9,5 @@ mod m { fn main() { m::leak_dyn_nonprincipal(); - //~^ ERROR type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private + //~^ ERROR trait `m::PrivNonPrincipal` is private } diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr index e15ca9d6dd410..2db4925722642 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -1,4 +1,4 @@ -error: type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private +error: trait `m::PrivNonPrincipal` is private --> $DIR/private-in-public-non-principal-2.rs:11:5 | LL | m::leak_dyn_nonprincipal(); diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs index df2f224c403ac..5de5a685208cd 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.rs +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -4,7 +4,7 @@ pub trait PubPrincipal {} auto trait PrivNonPrincipal {} pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } -//~^ WARN private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface +//~^ WARN private trait `PrivNonPrincipal` in public interface //~| WARN this was previously accepted #[deny(missing_docs)] diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 6c9da53ad3fe0..9967405589777 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -1,4 +1,4 @@ -warning: private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface (error E0446) +warning: private trait `PrivNonPrincipal` in public interface (error E0445) --> $DIR/private-in-public-non-principal.rs:6:1 | LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index 1eb5fa408cd7f..69b60a56c67f1 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -119,7 +119,7 @@ fn main() { m::leak_anon2(); //~ ERROR type `m::Priv` is private m::leak_anon3(); //~ ERROR type `m::Priv` is private - m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private + m::leak_dyn1(); //~ ERROR trait `m::Trait` is private m::leak_dyn2(); //~ ERROR type `m::Priv` is private m::leak_dyn3(); //~ ERROR type `m::Priv` is private diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index 089fb1d3c3ea8..80a475f7dceea 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -160,10 +160,10 @@ error: type `m::Priv` is private LL | m::leak_anon3(); //~ ERROR type `m::Priv` is private | ^^^^^^^^^^^^^^^ -error: type `(dyn m::Trait + 'static)` is private +error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:122:5 | -LL | m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private +LL | m::leak_dyn1(); //~ ERROR trait `m::Trait` is private | ^^^^^^^^^^^^^^ error: type `m::Priv` is private From 303e440b9315fa9659dea5f5a545a429ddebf692 Mon Sep 17 00:00:00 2001 From: Yu Ding <dingelish@gmail.com> Date: Mon, 31 Dec 2018 15:45:42 -0800 Subject: [PATCH 085/124] Bound sgx target_env with fortanix as target_vendor Signed-off-by: Yu Ding <dingelish@gmail.com> --- src/libpanic_abort/lib.rs | 3 ++- src/libstd/Cargo.toml | 2 +- src/libstd/lib.rs | 9 +++++---- src/libstd/sys/mod.rs | 10 +++++++--- src/libstd/sys_common/mod.rs | 2 +- src/libtest/lib.rs | 6 ++++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 4a22b69eda80b..d8dd2e0a11337 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -12,6 +12,7 @@ #![panic_runtime] #![allow(unused_features)] +#![feature(cfg_target_vendor)] #![feature(core_intrinsics)] #![feature(libc)] #![feature(nll)] @@ -57,7 +58,7 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { core::intrinsics::abort(); } - #[cfg(target_env="sgx")] + #[cfg(all(target_vendor="fortanix", target_env="sgx"))] unsafe fn abort() -> ! { extern "C" { pub fn panic_exit() -> !; } panic_exit(); diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5214f365a6476..92876f7f2d804 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -37,7 +37,7 @@ rustc_lsan = { path = "../librustc_lsan" } rustc_msan = { path = "../librustc_msan" } rustc_tsan = { path = "../librustc_tsan" } -[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))'.dependencies] +[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 6ded43dfed1f4..3b7e8291d3851 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -302,9 +302,10 @@ #![feature(non_exhaustive)] #![feature(alloc_layout_extra)] #![feature(maybe_uninit)] -#![cfg_attr(target_env = "sgx", feature(global_asm, range_contains, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform, - min_const_unsafe_fn))] +#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), + feature(global_asm, range_contains, slice_index_methods, + decl_macro, coerce_unsized, sgx_platform, + min_const_unsafe_fn))] #![default_lib_allocator] @@ -347,7 +348,7 @@ extern crate backtrace_sys; // testing gives test-std access to real-std lang items and globals. See #2912 #[cfg(test)] extern crate std as realstd; -#[cfg(target_env = "sgx")] +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] #[macro_use] #[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot // determine resolution for the macro `usercalls_asm`” diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index de9e09bf7057e..f398a2a6225ce 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -38,7 +38,7 @@ cfg_if! { } else if #[cfg(target_arch = "wasm32")] { mod wasm; pub use self::wasm::*; - } else if #[cfg(target_env = "sgx")] { + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use self::sgx::*; } else { @@ -55,7 +55,9 @@ cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available pub use self::ext as unix_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(any(target_os = "cloudabi", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] { // On CloudABI and wasm right now the module below doesn't compile // (missing things in `libc` which is empty) so just omit everything // with an empty module @@ -76,7 +78,9 @@ cfg_if! { // On windows we'll just be documenting what's already available #[allow(missing_docs)] pub use self::ext as windows_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(any(target_os = "cloudabi", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] { // On CloudABI and wasm right now the shim below doesn't compile, so // just omit it #[unstable(issue = "0", feature = "std_internals")] diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index ee3916b35f9c9..c18b603a6356c 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -51,7 +51,7 @@ cfg_if! { target_os = "l4re", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx"))] { + all(target_vendor = "fortanix", target_env = "sgx")))] { pub use sys::net; } else { pub mod net; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 4e227745a793f..ec96ea067082f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,6 +23,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(asm)] +#![feature(cfg_target_vendor)] #![feature(fnbox)] #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))] #![feature(nll)] @@ -1015,7 +1016,7 @@ fn use_color(opts: &TestOpts) -> bool { #[cfg(any(target_os = "cloudabi", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx"))] + all(target_vendor = "fortanix", target_env = "sgx")))] fn stdout_isatty() -> bool { // FIXME: Implement isatty on Redox and SGX false @@ -1246,7 +1247,8 @@ fn get_concurrency() -> usize { 1 } - #[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))] + #[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_vendor = "fortanix", target_env = "sgx")))] fn num_cpus() -> usize { 1 } From df9f594b9632f90233419e59688b0429cde8160b Mon Sep 17 00:00:00 2001 From: Yuning Zhang <codeworm96@outlook.com> Date: Mon, 31 Dec 2018 20:43:08 -0500 Subject: [PATCH 086/124] Improve type mismatch error messages Replace "integral variable" with "integer" and replace "floating-point variable" with "floating-point number" to make the message less confusing. --- src/librustc/ty/error.rs | 4 ++-- src/test/ui/bad/bad-const-type.rs | 2 +- src/test/ui/bad/bad-const-type.stderr | 2 +- src/test/ui/binop/binop-logic-int.stderr | 4 ++-- .../ui/blind/blind-item-block-middle.stderr | 2 +- src/test/ui/chalkify/type_inference.stderr | 2 +- src/test/ui/coercion/coerce-to-bang.stderr | 20 ++++++++--------- src/test/ui/consts/const-integer-bool-ops.rs | 16 +++++++------- .../ui/consts/const-integer-bool-ops.stderr | 16 +++++++------- src/test/ui/conversion-methods.stderr | 2 +- ...xpected-float-found-integer-literal.stderr | 10 ++++----- src/test/ui/error-codes/E0070.stderr | 2 +- ...loat-literal-inference-restrictions.stderr | 2 +- .../fully-qualified-type-name1.rs | 2 +- .../fully-qualified-type-name1.stderr | 2 +- .../generic-arg-mismatch-recover.stderr | 2 +- src/test/ui/if/if-let-arm-types.rs | 2 +- src/test/ui/if/if-let-arm-types.stderr | 4 ++-- .../ui/integral-variable-unification-error.rs | 2 +- ...integral-variable-unification-error.stderr | 2 +- src/test/ui/issues/issue-13407.stderr | 2 +- src/test/ui/issues/issue-14091.stderr | 2 +- src/test/ui/issues/issue-19991.rs | 2 +- src/test/ui/issues/issue-19991.stderr | 4 ++-- src/test/ui/issues/issue-33504.stderr | 2 +- src/test/ui/issues/issue-37665.stderr | 2 +- src/test/ui/issues/issue-4201.rs | 2 +- src/test/ui/issues/issue-4201.stderr | 4 ++-- src/test/ui/issues/issue-4968.rs | 2 +- src/test/ui/issues/issue-4968.stderr | 2 +- .../keyword-false-as-identifier.stderr | 2 +- .../keyword/keyword-true-as-identifier.stderr | 2 +- src/test/ui/loops/loop-break-value.stderr | 8 +++---- src/test/ui/match/match-range-fail.stderr | 2 +- src/test/ui/methods/method-self-arg-1.rs | 2 +- src/test/ui/methods/method-self-arg-1.stderr | 2 +- src/test/ui/mir-unpretty.stderr | 2 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/mismatched_types/abridged.stderr | 4 ++-- .../for-loop-has-unit-body.stderr | 2 +- .../ui/proc-macro/span-preservation.stderr | 2 +- src/test/ui/repeat_count.rs | 2 +- src/test/ui/repeat_count.stderr | 2 +- .../slightly-nice-generic-literal-messages.rs | 2 +- ...ghtly-nice-generic-literal-messages.stderr | 2 +- .../ui/structs/struct-base-wrong-type-2.rs | 2 +- .../structs/struct-base-wrong-type-2.stderr | 2 +- src/test/ui/structs/struct-base-wrong-type.rs | 2 +- .../ui/structs/struct-base-wrong-type.stderr | 2 +- .../structure-constructor-type-mismatch.rs | 12 +++++----- ...structure-constructor-type-mismatch.stderr | 22 +++++++++---------- .../ui/try-block/try-block-type-error.stderr | 2 +- src/test/ui/type/type-mismatch-multiple.rs | 2 +- .../ui/type/type-mismatch-multiple.stderr | 2 +- 54 files changed, 105 insertions(+), 105 deletions(-) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index c491fdd9957e8..6b931e39a05da 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -200,8 +200,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), - ty::Infer(ty::IntVar(_)) => "integral variable".into(), - ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), + ty::Infer(ty::IntVar(_)) => "integer".into(), + ty::Infer(ty::FloatVar(_)) => "floating-point number".into(), ty::Placeholder(..) => "placeholder type".into(), ty::Bound(..) => "bound type".into(), ty::Infer(ty::FreshTy(_)) => "fresh type".into(), diff --git a/src/test/ui/bad/bad-const-type.rs b/src/test/ui/bad/bad-const-type.rs index b46f5933010de..8121929e09675 100644 --- a/src/test/ui/bad/bad-const-type.rs +++ b/src/test/ui/bad/bad-const-type.rs @@ -2,5 +2,5 @@ static i: String = 10; //~^ ERROR mismatched types //~| expected type `std::string::String` //~| found type `{integer}` -//~| expected struct `std::string::String`, found integral variable +//~| expected struct `std::string::String`, found integer fn main() { println!("{}", i); } diff --git a/src/test/ui/bad/bad-const-type.stderr b/src/test/ui/bad/bad-const-type.stderr index 694e692a5bec5..677dc72652e92 100644 --- a/src/test/ui/bad/bad-const-type.stderr +++ b/src/test/ui/bad/bad-const-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | static i: String = 10; | ^^ | | - | expected struct `std::string::String`, found integral variable + | expected struct `std::string::String`, found integer | help: try using a conversion method: `10.to_string()` | = note: expected type `std::string::String` diff --git a/src/test/ui/binop/binop-logic-int.stderr b/src/test/ui/binop/binop-logic-int.stderr index 9ca9e64211c82..b699b390b8bb1 100644 --- a/src/test/ui/binop/binop-logic-int.stderr +++ b/src/test/ui/binop/binop-logic-int.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/binop-logic-int.rs:1:21 | LL | fn main() { let x = 1 && 2; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/binop-logic-int.rs:1:26 | LL | fn main() { let x = 1 && 2; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index 05a623404493a..389b63c0adf93 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/blind-item-block-middle.rs:6:9 | LL | let bar = 5; - | ^^^ expected integral variable, found struct `foo::bar` + | ^^^ expected integer, found struct `foo::bar` | = note: expected type `{integer}` found type `foo::bar` diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 49ed97d71680b..d65b701307b43 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type_inference.rs:21:14 | LL | only_foo(x); //~ ERROR mismatched types - | ^ expected i32, found floating-point variable + | ^ expected i32, found floating-point number | = note: expected type `i32` found type `{float}` diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr index 0795765ef2d8e..72e7211de7a7f 100644 --- a/src/test/ui/coercion/coerce-to-bang.stderr +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:6:17 | LL | foo(return, 22, 44); - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:18:13 | LL | foo(22, 44, return); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 | LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 | LL | foo(a, b, c); //~ ERROR mismatched types - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 | LL | foo(a, b, c); //~ ERROR mismatched types - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -47,7 +47,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:50:21 | LL | let x: [!; 2] = [return, 22]; //~ ERROR mismatched types - | ^^^^^^^^^^^^ expected !, found integral variable + | ^^^^^^^^^^^^ expected !, found integer | = note: expected type `[!; 2]` found type `[{integer}; 2]` @@ -56,7 +56,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:55:22 | LL | let x: [!; 2] = [22, return]; //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -65,7 +65,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:60:37 | LL | let x: (usize, !, usize) = (22, 44, 66); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -74,7 +74,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:65:41 | LL | let x: (usize, !, usize) = (return, 44, 66); - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -83,7 +83,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:76:37 | LL | let x: (usize, !, usize) = (22, 44, return); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index d557d70a52f10..f0d5a558e3529 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -1,8 +1,8 @@ const X: usize = 42 && 39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR: [i32; X] = [99; 34]; @@ -10,9 +10,9 @@ const ARR: [i32; X] = [99; 34]; const X1: usize = 42 || 39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR1: [i32; X1] = [99; 47]; @@ -20,9 +20,9 @@ const ARR1: [i32; X1] = [99; 47]; const X2: usize = -42 || -39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR2: [i32; X2] = [99; 18446744073709551607]; @@ -30,9 +30,9 @@ const ARR2: [i32; X2] = [99; 18446744073709551607]; const X3: usize = -42 && -39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR3: [i32; X3] = [99; 6]; diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 8ac3f617a3670..7885eb446f0dd 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:1:18 | LL | const X: usize = 42 && 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:1:24 | LL | const X: usize = 42 && 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -32,7 +32,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:11:19 | LL | const X1: usize = 42 || 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -41,7 +41,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:11:25 | LL | const X1: usize = 42 || 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:21:19 | LL | const X2: usize = -42 || -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -71,7 +71,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:21:26 | LL | const X2: usize = -42 || -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -92,7 +92,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:31:19 | LL | const X3: usize = -42 && -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -101,7 +101,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:31:26 | LL | const X3: usize = -42 && -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr index 78099ea9e7cca..33fff4a0f68ed 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/conversion-methods.stderr @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here | ^ | | - | expected struct `std::string::String`, found integral variable + | expected struct `std::string::String`, found integer | help: try using a conversion method: `2.to_string()` | = note: expected type `std::string::String` diff --git a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr index 9f09c9b53ccea..301704ec0c7ef 100644 --- a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr +++ b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let sixteen: f32 = 16; | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `16.0` | = note: expected type `f32` @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | let a_million_and_seventy: f64 = 1_000_070; | ^^^^^^^^^ | | - | expected f64, found integral variable + | expected f64, found integer | help: use a float literal: `1_000_070.0` | = note: expected type `f64` @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | let negative_nine: f32 = -9; | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `-9.0` | = note: expected type `f32` @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:15:30 | LL | let sixteen_again: f64 = 0x10; - | ^^^^ expected f64, found integral variable + | ^^^^ expected f64, found integer | = note: expected type `f64` found type `{integer}` @@ -47,7 +47,7 @@ error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:17:30 | LL | let and_once_more: f32 = 0o20; - | ^^^^ expected f32, found integral variable + | ^^^^ expected f32, found integer | = note: expected type `f32` found type `{integer}` diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index a6a8925d99142..4c1cfd858e6c5 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/E0070.rs:8:25 | LL | some_other_func() = 4; //~ ERROR E0070 - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/float-literal-inference-restrictions.stderr index ea12c9caa77cc..a69c13507e6b2 100644 --- a/src/test/ui/float-literal-inference-restrictions.stderr +++ b/src/test/ui/float-literal-inference-restrictions.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let x: f32 = 1; //~ ERROR mismatched types | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `1.0` | = note: expected type `f32` diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 8fdcbbae8debf..7e5b884103ed2 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -6,5 +6,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `std::option::Option<usize>` //~| found type `{integer}` - //~| expected enum `std::option::Option`, found integral variable + //~| expected enum `std::option::Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index d16cbcfe1d5f4..62ded3e255a44 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | x = 5; | ^ | | - | expected enum `std::option::Option`, found integral variable + | expected enum `std::option::Option`, found integer | help: try using a variant of the expected type: `Some(5)` | = note: expected type `std::option::Option<usize>` diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.stderr b/src/test/ui/generic/generic-arg-mismatch-recover.stderr index 1576b3c3915f9..37f6c61f06df3 100644 --- a/src/test/ui/generic/generic-arg-mismatch-recover.stderr +++ b/src/test/ui/generic/generic-arg-mismatch-recover.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/generic-arg-mismatch-recover.rs:6:33 | LL | Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments - | ^^ expected (), found integral variable + | ^^ expected (), found integer | = note: expected type `&'static ()` found type `&{integer}` diff --git a/src/test/ui/if/if-let-arm-types.rs b/src/test/ui/if/if-let-arm-types.rs index ca115cc219e95..749c089ae9752 100644 --- a/src/test/ui/if/if-let-arm-types.rs +++ b/src/test/ui/if/if-let-arm-types.rs @@ -1,6 +1,6 @@ fn main() { if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types - //~^ expected (), found integral variable + //~^ expected (), found integer //~| expected type `()` //~| found type `{integer}` () diff --git a/src/test/ui/if/if-let-arm-types.stderr b/src/test/ui/if/if-let-arm-types.stderr index 23cf5a45af055..fcf9e4695f675 100644 --- a/src/test/ui/if/if-let-arm-types.stderr +++ b/src/test/ui/if/if-let-arm-types.stderr @@ -2,13 +2,13 @@ error[E0308]: `if let` arms have incompatible types --> $DIR/if-let-arm-types.rs:2:5 | LL | / if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types -LL | | //~^ expected (), found integral variable +LL | | //~^ expected (), found integer LL | | //~| expected type `()` LL | | //~| found type `{integer}` ... | LL | | 1 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 98a77e9c82f67..3eefcdea3d902 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -4,5 +4,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `{integer}` //~| found type `{float}` - //~| expected integral variable, found floating-point variable + //~| expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index 7670f7a0e8da7..262203b7b8e4d 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/integral-variable-unification-error.rs:3:9 | LL | x = 5.0; - | ^^^ expected integral variable, found floating-point variable + | ^^^ expected integer, found floating-point number | = note: expected type `{integer}` found type `{float}` diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 90b5d22a28425..1f4c7dfb0da02 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/issue-13407.rs:6:12 | LL | A::C = 1; - | ^ expected struct `A::C`, found integral variable + | ^ expected struct `A::C`, found integer | = note: expected type `A::C` found type `{integer}` diff --git a/src/test/ui/issues/issue-14091.stderr b/src/test/ui/issues/issue-14091.stderr index c7616e5ab4f41..24a076624edee 100644 --- a/src/test/ui/issues/issue-14091.stderr +++ b/src/test/ui/issues/issue-14091.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-14091.rs:2:5 | LL | assert!(1,1); - | ^^^^^^^^^^^^^ expected bool, found integral variable + | ^^^^^^^^^^^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/issues/issue-19991.rs b/src/test/ui/issues/issue-19991.rs index 349a1d77c2b7c..e9094ecc01589 100644 --- a/src/test/ui/issues/issue-19991.rs +++ b/src/test/ui/issues/issue-19991.rs @@ -5,7 +5,7 @@ fn main() { if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause //~| expected type `()` //~| found type `{integer}` - //~| expected (), found integral variable + //~| expected (), found integer 765 }; } diff --git a/src/test/ui/issues/issue-19991.stderr b/src/test/ui/issues/issue-19991.stderr index cf3d55e821091..ee5d363c4bd2b 100644 --- a/src/test/ui/issues/issue-19991.stderr +++ b/src/test/ui/issues/issue-19991.stderr @@ -4,10 +4,10 @@ error[E0317]: if may be missing an else clause LL | / if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause LL | | //~| expected type `()` LL | | //~| found type `{integer}` -LL | | //~| expected (), found integral variable +LL | | //~| expected (), found integer LL | | 765 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index 95d6c55c1ea50..716aa8a863292 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-33504.rs:7:13 | LL | let Test = 1; //~ ERROR mismatched types - | ^^^^ expected integral variable, found struct `Test` + | ^^^^ expected integer, found struct `Test` | = note: expected type `{integer}` found type `Test` diff --git a/src/test/ui/issues/issue-37665.stderr b/src/test/ui/issues/issue-37665.stderr index 0022ab73e1ad9..c3599fab68507 100644 --- a/src/test/ui/issues/issue-37665.stderr +++ b/src/test/ui/issues/issue-37665.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-37665.rs:10:17 | LL | let x: () = 0; //~ ERROR: mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-4201.rs b/src/test/ui/issues/issue-4201.rs index c9098c843f92f..2f1d6d2177e40 100644 --- a/src/test/ui/issues/issue-4201.rs +++ b/src/test/ui/issues/issue-4201.rs @@ -5,7 +5,7 @@ fn main() { //~^ ERROR if may be missing an else clause //~| expected type `()` //~| found type `{integer}` -//~| expected (), found integral variable +//~| expected (), found integer 1 }; } diff --git a/src/test/ui/issues/issue-4201.stderr b/src/test/ui/issues/issue-4201.stderr index ebeb870183e45..4f8ec96d53151 100644 --- a/src/test/ui/issues/issue-4201.stderr +++ b/src/test/ui/issues/issue-4201.stderr @@ -6,10 +6,10 @@ LL | } else if false { LL | | //~^ ERROR if may be missing an else clause LL | | //~| expected type `()` LL | | //~| found type `{integer}` -LL | | //~| expected (), found integral variable +LL | | //~| expected (), found integer LL | | 1 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-4968.rs b/src/test/ui/issues/issue-4968.rs index 3bf65c5ce8e6e..383b9ecd466fe 100644 --- a/src/test/ui/issues/issue-4968.rs +++ b/src/test/ui/issues/issue-4968.rs @@ -6,5 +6,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `{integer}` //~| found type `(isize, isize)` - //~| expected integral variable, found tuple + //~| expected integer, found tuple } diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 2f6b4b95882fc..a925783723b44 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-4968.rs:5:16 | LL | match 42 { A => () } - | ^ expected integral variable, found tuple + | ^ expected integer, found tuple | = note: expected type `{integer}` found type `(isize, isize)` diff --git a/src/test/ui/keyword/keyword-false-as-identifier.stderr b/src/test/ui/keyword/keyword-false-as-identifier.stderr index de5dfcfbe4360..6c8dffa7e22c6 100644 --- a/src/test/ui/keyword/keyword-false-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-false-as-identifier.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/keyword-false-as-identifier.rs:2:9 | LL | let false = 22; //~ error: mismatched types - | ^^^^^ expected integral variable, found bool + | ^^^^^ expected integer, found bool | = note: expected type `{integer}` found type `bool` diff --git a/src/test/ui/keyword/keyword-true-as-identifier.stderr b/src/test/ui/keyword/keyword-true-as-identifier.stderr index cc5c6fe45565f..e5d3938e54ac2 100644 --- a/src/test/ui/keyword/keyword-true-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-true-as-identifier.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/keyword-true-as-identifier.rs:2:9 | LL | let true = 22; //~ error: mismatched types - | ^^^^ expected integral variable, found bool + | ^^^^ expected integer, found bool | = note: expected type `{integer}` found type `bool` diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 8fc4ec94366a5..3e009c007e08d 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -91,7 +91,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:11:19 | LL | break 123; //~ ERROR mismatched types - | ^^^ expected &str, found integral variable + | ^^^ expected &str, found integer | = note: expected type `&str` found type `{integer}` @@ -118,7 +118,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:73:26 | LL | break 'c 123; //~ ERROR mismatched types - | ^^^ expected (), found integral variable + | ^^^ expected (), found integer | = note: expected type `()` found type `{integer}` @@ -136,7 +136,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:85:15 | LL | break 2; //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` @@ -145,7 +145,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:90:9 | LL | break; //~ ERROR mismatched types - | ^^^^^ expected (), found integral variable + | ^^^^^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 8d067c703b731..54969927433a4 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/match-range-fail.rs:17:9 | LL | 'c' ..= 100 => { } - | ^^^^^^^^^^^ expected integral variable, found char + | ^^^^^^^^^^^ expected integer, found char | = note: expected type `{integer}` found type `char` diff --git a/src/test/ui/methods/method-self-arg-1.rs b/src/test/ui/methods/method-self-arg-1.rs index 48be31d94f2ee..4a78ad780c412 100644 --- a/src/test/ui/methods/method-self-arg-1.rs +++ b/src/test/ui/methods/method-self-arg-1.rs @@ -15,5 +15,5 @@ fn main() { Foo::bar(&42); //~ ERROR mismatched types //~| expected type `&Foo` //~| found type `&{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } diff --git a/src/test/ui/methods/method-self-arg-1.stderr b/src/test/ui/methods/method-self-arg-1.stderr index 0756e9b68f2a3..8c80d01b18cb9 100644 --- a/src/test/ui/methods/method-self-arg-1.stderr +++ b/src/test/ui/methods/method-self-arg-1.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/method-self-arg-1.rs:15:14 | LL | Foo::bar(&42); //~ ERROR mismatched types - | ^^^ expected struct `Foo`, found integral variable + | ^^^ expected struct `Foo`, found integer | = note: expected type `&Foo` found type `&{integer}` diff --git a/src/test/ui/mir-unpretty.stderr b/src/test/ui/mir-unpretty.stderr index 913999c2290ba..59e8c0bf09029 100644 --- a/src/test/ui/mir-unpretty.stderr +++ b/src/test/ui/mir-unpretty.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/mir-unpretty.rs:4:17 | LL | let x: () = 0; //~ ERROR: mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index 4d5bfceb74e95..08f132efd0526 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 - | ^ expected &{integer}, found integral variable + | ^ expected &{integer}, found integer | = note: expected type `&{integer}` found type `{integer}` diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 5256148c771f3..6a5cf7db4eed9 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -49,7 +49,7 @@ LL | fn d() -> X<X<String, String>, String> { | ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type ... LL | x //~ ERROR mismatched types - | ^ expected struct `std::string::String`, found integral variable + | ^ expected struct `std::string::String`, found integer | = note: expected type `X<X<_, std::string::String>, std::string::String>` found type `X<X<_, {integer}>, {integer}>` @@ -61,7 +61,7 @@ LL | fn e() -> X<X<String, String>, String> { | ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type ... LL | x //~ ERROR mismatched types - | ^ expected struct `std::string::String`, found integral variable + | ^ expected struct `std::string::String`, found integer | = note: expected type `X<X<_, std::string::String>, _>` found type `X<X<_, {integer}>, _>` diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr index 1de8e18c587ba..25203d6f35d28 100644 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/for-loop-has-unit-body.rs:3:9 | LL | x //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 64d0173cb9c22..1f9103a6d2ee8 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | extern "C" fn baz() { | - possibly return type missing here? LL | 0 //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/repeat_count.rs b/src/test/ui/repeat_count.rs index 74385c7949790..c42dc8c99719d 100644 --- a/src/test/ui/repeat_count.rs +++ b/src/test/ui/repeat_count.rs @@ -16,7 +16,7 @@ fn main() { //~^ ERROR mismatched types //~| expected type `usize` //~| found type `{float}` - //~| expected usize, found floating-point variable + //~| expected usize, found floating-point number let e = [0; "foo"]; //~^ ERROR mismatched types //~| expected type `usize` diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index b481cd187c597..df3227bfcde13 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -23,7 +23,7 @@ error[E0308]: mismatched types --> $DIR/repeat_count.rs:15:17 | LL | let d = [0; 0.5]; - | ^^^ expected usize, found floating-point variable + | ^^^ expected usize, found floating-point number | = note: expected type `usize` found type `{float}` diff --git a/src/test/ui/slightly-nice-generic-literal-messages.rs b/src/test/ui/slightly-nice-generic-literal-messages.rs index fcbc2a169a53c..cd0ee174af528 100644 --- a/src/test/ui/slightly-nice-generic-literal-messages.rs +++ b/src/test/ui/slightly-nice-generic-literal-messages.rs @@ -8,7 +8,7 @@ fn main() { //~^ ERROR mismatched types //~| expected type `Foo<{float}, _>` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } } diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr index 767faf5291488..76ebc007df34f 100644 --- a/src/test/ui/slightly-nice-generic-literal-messages.stderr +++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/slightly-nice-generic-literal-messages.rs:7:9 | LL | 1 => {} - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo<{float}, _>` found type `{integer}` diff --git a/src/test/ui/structs/struct-base-wrong-type-2.rs b/src/test/ui/structs/struct-base-wrong-type-2.rs index a88c5d1c13b48..562f75b8e85bd 100644 --- a/src/test/ui/structs/struct-base-wrong-type-2.rs +++ b/src/test/ui/structs/struct-base-wrong-type-2.rs @@ -15,5 +15,5 @@ fn main() { let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types //~| expected type `Foo` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } diff --git a/src/test/ui/structs/struct-base-wrong-type-2.stderr b/src/test/ui/structs/struct-base-wrong-type-2.stderr index 44ac3483ad6d1..b15ea51bb2d4c 100644 --- a/src/test/ui/structs/struct-base-wrong-type-2.stderr +++ b/src/test/ui/structs/struct-base-wrong-type-2.stderr @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/struct-base-wrong-type-2.rs:15:34 | LL | let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo` found type `{integer}` diff --git a/src/test/ui/structs/struct-base-wrong-type.rs b/src/test/ui/structs/struct-base-wrong-type.rs index 83b5444815159..6252673c296fb 100644 --- a/src/test/ui/structs/struct-base-wrong-type.rs +++ b/src/test/ui/structs/struct-base-wrong-type.rs @@ -14,7 +14,7 @@ static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types //~| expected type `Foo` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer fn main() { let b = Bar { x: 5 }; diff --git a/src/test/ui/structs/struct-base-wrong-type.stderr b/src/test/ui/structs/struct-base-wrong-type.stderr index 8519a9510a9fa..045eb610f7d1f 100644 --- a/src/test/ui/structs/struct-base-wrong-type.stderr +++ b/src/test/ui/structs/struct-base-wrong-type.stderr @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/struct-base-wrong-type.rs:14:35 | LL | static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo` found type `{integer}` diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs index 54319e1ea4fc4..8850f6ea89fa3 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.rs +++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs @@ -16,32 +16,32 @@ fn main() { let pt = PointF { x: 1, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 2, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer }; let pt2 = Point::<f32> { x: 3, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 4, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer }; let pair = PairF { x: 5, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 6, }; let pair2 = PairF::<i32> { x: 7, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 8, }; diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr index 6abc75110e1f0..3c1ed8e69a6bd 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | x: 1, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `1.0` | = note: expected type `f32` @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | y: 2, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `2.0` | = note: expected type `f32` @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | x: 3, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `3.0` | = note: expected type `f32` @@ -40,7 +40,7 @@ error[E0308]: mismatched types LL | y: 4, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `4.0` | = note: expected type `f32` @@ -52,7 +52,7 @@ error[E0308]: mismatched types LL | x: 5, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `5.0` | = note: expected type `f32` @@ -64,7 +64,7 @@ error[E0308]: mismatched types LL | x: 7, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `7.0` | = note: expected type `f32` @@ -82,7 +82,7 @@ error[E0308]: mismatched types LL | x: 9, //~ ERROR mismatched types | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `9.0` | = note: expected type `f32` @@ -94,7 +94,7 @@ error[E0308]: mismatched types LL | y: 10, //~ ERROR mismatched types | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `10.0` | = note: expected type `f32` @@ -110,7 +110,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:54:9 | LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments - | ^^^^^^^^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Point<{integer}>` found type `Point<f32>` @@ -119,7 +119,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:59:9 | LL | PointF { .. } => {} //~ ERROR mismatched types - | ^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Point<{integer}>` found type `Point<f32>` @@ -128,7 +128,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:67:9 | LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types - | ^^^^^^^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Pair<{integer}, {integer}>` found type `Pair<f32, u32>` diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr index cf52c4ce15266..0cbd737debde5 100644 --- a/src/test/ui/try-block/try-block-type-error.stderr +++ b/src/test/ui/try-block/try-block-type-error.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Tr LL | 42 | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `42.0` | = note: expected type `f32` diff --git a/src/test/ui/type/type-mismatch-multiple.rs b/src/test/ui/type/type-mismatch-multiple.rs index f2e289a11b75e..1904ccf5d5945 100644 --- a/src/test/ui/type/type-mismatch-multiple.rs +++ b/src/test/ui/type/type-mismatch-multiple.rs @@ -4,7 +4,7 @@ fn main() { let a: bool = 1; let b: i32 = true; } //~^ ERROR mismatched types //~| expected type `bool` //~| found type `{integer}` -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected i32, found bool diff --git a/src/test/ui/type/type-mismatch-multiple.stderr b/src/test/ui/type/type-mismatch-multiple.stderr index b38579046b585..8f6b23ea091a2 100644 --- a/src/test/ui/type/type-mismatch-multiple.stderr +++ b/src/test/ui/type/type-mismatch-multiple.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-multiple.rs:3:27 | LL | fn main() { let a: bool = 1; let b: i32 = true; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` From 98d45895aa99ba2c480942a295f1cc266ca94df9 Mon Sep 17 00:00:00 2001 From: Yu Ding <dingelish@gmail.com> Date: Tue, 1 Jan 2019 11:49:54 -0800 Subject: [PATCH 087/124] Remove min_const_unsafe_fn since it is stable Signed-off-by: Yu Ding <dingelish@gmail.com> --- src/libstd/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3b7e8291d3851..d42e39f16e663 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -304,8 +304,7 @@ #![feature(maybe_uninit)] #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), feature(global_asm, range_contains, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform, - min_const_unsafe_fn))] + decl_macro, coerce_unsized, sgx_platform))] #![default_lib_allocator] From b25abf1a82b39f8f73524a45237c11e8ee2aee38 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Tue, 1 Jan 2019 19:14:00 +0300 Subject: [PATCH 088/124] syntax: Fix regression in diagnostics for patterns in trait method parameters --- src/libsyntax/parse/parser.rs | 3 ++- src/test/ui/E0642.rs | 2 ++ src/test/ui/E0642.stderr | 12 +++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7c471fdebb3a0..1e4a26b353759 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1878,7 +1878,8 @@ impl<'a> Parser<'a> { let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment("a method argument's type"); let mut ty = self.parse_ty(); - if ty.is_ok() && self.token == token::Colon { + if ty.is_ok() && self.token != token::Comma && + self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, // so we are going to rollback and re-parse for recovery. ty = self.unexpected(); diff --git a/src/test/ui/E0642.rs b/src/test/ui/E0642.rs index 8b74e5abe19df..cfbd362c1da19 100644 --- a/src/test/ui/E0642.rs +++ b/src/test/ui/E0642.rs @@ -6,6 +6,8 @@ trait T { fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies + fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies + fn f(&ident: &S) {} // ok fn g(&&ident: &&S) {} // ok fn h(mut ident: S) {} // ok diff --git a/src/test/ui/E0642.stderr b/src/test/ui/E0642.stderr index c3a230d5acf3c..4c82a6cbd21b4 100644 --- a/src/test/ui/E0642.stderr +++ b/src/test/ui/E0642.stderr @@ -18,6 +18,16 @@ help: give this argument a name or use an underscore to ignore it LL | fn bar(_: (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies | ^ -error: aborting due to 2 previous errors +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/E0642.rs:9:15 + | +LL | fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies + | ^^^^^^^^ +help: give this argument a name or use an underscore to ignore it + | +LL | fn method(_: S) {} //~ ERROR patterns aren't allowed in methods without bodies + | ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0642`. From 454f7cbf59a0d6cd047f1313480d96874da84470 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 4 Dec 2018 10:03:34 -0500 Subject: [PATCH 089/124] generate invalidations from 2-phase-borrow activations --- .../borrow_check/nll/invalidation.rs | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 76b516246f92a..112b39952559b 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -56,10 +56,14 @@ struct InvalidationGenerator<'cx, 'tcx: 'cx, 'gcx: 'tcx> { /// Visits the whole MIR and generates invalidates() facts /// Most of the code implementing this was stolen from borrow_check/mod.rs impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { - fn visit_statement(&mut self, - block: BasicBlock, - statement: &Statement<'tcx>, - location: Location) { + fn visit_statement( + &mut self, + block: BasicBlock, + statement: &Statement<'tcx>, + location: Location, + ) { + self.check_activations(location); + match statement.kind { StatementKind::Assign(ref lhs, ref rhs) => { self.consume_rvalue( @@ -148,6 +152,8 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { terminator: &Terminator<'tcx>, location: Location ) { + self.check_activations(location); + match terminator.kind { TerminatorKind::SwitchInt { ref discr, @@ -471,5 +477,41 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> { let lidx = self.location_table.start_index(l); self.all_facts.invalidates.push((lidx, b)); } + + fn check_activations( + &mut self, + location: Location, + ) { + if !self.tcx.two_phase_borrows() { + return; + } + + // Two-phase borrow support: For each activation that is newly + // generated at this statement, check if it interferes with + // another borrow. + for &borrow_index in self.borrow_set.activations_at_location(location) { + let borrow = &self.borrow_set[borrow_index]; + + // only mutable borrows should be 2-phase + assert!(match borrow.kind { + BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Unique | BorrowKind::Mut { .. } => true, + }); + + self.access_place( + ContextKind::Activation.new(location), + &borrow.borrowed_place, + ( + Deep, + Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), + ), + LocalMutationIsAllowed::No, + ); + + // We do not need to call `check_if_path_or_subpath_is_moved` + // again, as we already called it when we made the + // initial reservation. + } + } } From 4bb9ecda27898c542077fdaf1fd8f99b6db5b685 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Wed, 2 Jan 2019 14:45:22 -0500 Subject: [PATCH 090/124] adopt polonius-engine 0.6.2 Also datafrog 2.0.1, which works around a rustdoc bug --- Cargo.lock | 14 +++++++------- src/librustc/Cargo.toml | 2 +- src/librustc_mir/Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 328c145edc4dd..041a24aae6c53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -617,7 +617,7 @@ dependencies = [ [[package]] name = "datafrog" -version = "0.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1622,10 +1622,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "polonius-engine" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2071,7 +2071,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_apfloat 0.0.0", @@ -2523,7 +2523,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", @@ -3428,7 +3428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" -"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" +"checksum datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" @@ -3537,7 +3537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201" +"checksum polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2490c396085801abf88df91758bad806b0890354f0875d624e62ecf0579a8145" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 8604efbc5742d..504e016e5b803 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -17,7 +17,7 @@ jobserver = "0.1" lazy_static = "1.0.0" scoped-tls = { version = "0.1.1", features = ["nightly"] } log = { version = "0.4", features = ["release_max_level_info", "std"] } -polonius-engine = "0.5.0" +polonius-engine = "0.6.2" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 5044e351962ed..f0234c48c3eca 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ either = "1.5.0" graphviz = { path = "../libgraphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.5.0" +polonius-engine = "0.6.2" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } From ce6192c748ec9f101b5aaa7bae0edaa9fcd86215 Mon Sep 17 00:00:00 2001 From: Matthew Jasper <mjjasper1@gmail.com> Date: Wed, 2 Jan 2019 20:00:56 +0000 Subject: [PATCH 091/124] Wf-check the output type of a function in MIR-typeck --- .../borrow_check/nll/type_check/mod.rs | 2 +- .../nll/issue-57265-return-type-wf-check.rs | 26 +++++++++++++++++++ .../issue-57265-return-type-wf-check.stderr | 12 +++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/nll/issue-57265-return-type-wf-check.rs create mode 100644 src/test/ui/nll/issue-57265-return-type-wf-check.stderr diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 796a2f79f7554..8bb67521f4431 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1452,7 +1452,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.check_call_dest(mir, term, &sig, destination, term_location); self.prove_predicates( - sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)), + sig.inputs_and_output.iter().map(|ty| ty::Predicate::WellFormed(ty)), term_location.to_locations(), ConstraintCategory::Boring, ); diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.rs b/src/test/ui/nll/issue-57265-return-type-wf-check.rs new file mode 100644 index 0000000000000..24c61a4926f0c --- /dev/null +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.rs @@ -0,0 +1,26 @@ +#![feature(nll)] + +use std::any::Any; + +#[derive(Debug, Clone)] +struct S<T: 'static>(T); + +// S<&'a T> is in the return type, so we get an implied bound +// &'a T: 'static +fn foo<'a, T>(x: &'a T) -> (S<&'a T>, Box<dyn Any + 'static>) { + let y = S(x); + + let z = Box::new(y.clone()) as Box<dyn Any + 'static>; + (y, z) +} + +fn main() { + let x = 5; + + // Check that we require that the argument is of type `&'static String`, + // so that the return type is well-formed. + let (_, z) = foo(&"hello".to_string()); + //~^ ERROR temporary value dropped while borrowed + + println!("{:?}", z.downcast_ref::<S<&'static String>>()); +} diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr new file mode 100644 index 0000000000000..db01212597f5b --- /dev/null +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-57265-return-type-wf-check.rs:22:23 + | +LL | let (_, z) = foo(&"hello".to_string()); + | -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. From 9c9411a735c2532d4cadf21471476025c0763f2b Mon Sep 17 00:00:00 2001 From: Matthew Jasper <mjjasper1@gmail.com> Date: Wed, 2 Jan 2019 21:28:08 +0000 Subject: [PATCH 092/124] Add missing 'static bound for the Machine trait --- src/librustc_mir/interpret/machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 1242c41a3562b..26d526a6f5ff8 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -76,7 +76,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { type MemoryExtra: Default; /// Extra data stored in every allocation. - type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra>; + type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra> + 'static; /// Memory's allocation map type MemoryMap: From db29f096e7beb87477bda6e77b1101d3ad28549c Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 15 Oct 2018 17:20:10 -0400 Subject: [PATCH 093/124] remove `commit_if_ok` wrapper --- src/librustc/traits/select.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index bd347764cc681..1832d35e3ae45 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -549,15 +549,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx.probe(|snapshot| f(self, snapshot)) } - /// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if - /// the transaction fails and s.t. old obligations are retained. - fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E> - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result<T, E>, - { - self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -3041,7 +3032,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // reported an ambiguity. (When we do find a match, also // record it for later.) let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while( - |&t| match self.commit_if_ok(|this, _| this.match_poly_trait_ref(obligation, t)) { + |&t| match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) { Ok(obligations) => { upcast_trait_ref = Some(t); nested.extend(obligations); From a7ec1072716ea4bdff73841bfe41ce321bb20fc9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 15 Oct 2018 17:28:37 -0400 Subject: [PATCH 094/124] remove wrapper functions that had no purpose --- src/librustc/traits/select.rs | 93 ++++++++++++++--------------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 1832d35e3ae45..e7c01df3dca0a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -29,8 +29,7 @@ use super::{ use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; -use infer; -use infer::{InferCtxt, InferOk, TypeFreshener}; +use infer::{self, InferCtxt, InferOk, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; @@ -531,24 +530,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx } - /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection - /// context's self. - fn in_snapshot<R, F>(&mut self, f: F) -> R - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, - { - self.infcx.in_snapshot(|snapshot| f(self, snapshot)) - } - - /// Wraps a probe s.t. obligations collected during it are ignored and old obligations are - /// retained. - fn probe<R, F>(&mut self, f: F) -> R - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, - { - self.infcx.probe(|snapshot| f(self, snapshot)) - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -630,8 +611,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, obligation: &PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - self.probe(|this, _| { - this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + self.infcx.probe(|_| { + self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) }) } @@ -1066,10 +1047,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate ); - let result = self.probe(|this, _| { + let result = self.infcx.probe(|_| { let candidate = (*candidate).clone(); - match this.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => this.evaluate_predicates_recursively( + match self.confirm_candidate(stack.obligation, candidate) { + Ok(selection) => self.evaluate_predicates_recursively( stack.list(), selection.nested_obligations().iter(), ), @@ -1697,8 +1678,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => return, } - let result = self.probe(|this, snapshot| { - this.match_projection_obligation_against_definition_bounds(obligation, snapshot) + let result = self.infcx.probe(|snapshot| { + self.match_projection_obligation_against_definition_bounds(obligation, snapshot) }); if result { @@ -1750,8 +1731,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates) .filter_to_traits() .find(|bound| { - self.probe(|this, _| { - this.match_projection( + self.infcx.probe(|_| { + self.match_projection( obligation, bound.clone(), skol_trait_predicate.trait_ref.clone(), @@ -1853,10 +1834,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - self.probe(move |this, _| { - match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { + self.infcx.probe(|_| { + match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { - this.evaluate_predicates_recursively(stack.list(), obligations.iter()) + self.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => Ok(EvaluatedToErr), } @@ -2006,8 +1987,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.probe(|this, snapshot| { - if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot) + self.infcx.probe(|snapshot| { + if let Ok(placeholder_map) = self.match_impl(impl_def_id, obligation, snapshot) { candidates.vec.push(ImplCandidate(impl_def_id)); @@ -2084,11 +2065,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.self_ty().skip_binder() ); - self.probe(|this, _snapshot| { + self.infcx.probe(|_snapshot| { // The code below doesn't care about regions, and the // self-ty here doesn't escape this probe, so just erase // any LBR. - let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); + let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { ty::Dynamic(ref data, ..) => { if data.auto_traits() @@ -2102,7 +2083,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - data.principal().with_self_ty(this.tcx(), self_ty) + data.principal().with_self_ty(self.tcx(), self_ty) } ty::Infer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -2122,11 +2103,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar<i32>`, // but `Foo` is declared as `trait Foo : Bar<u32>`. - let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref) + let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) .filter(|upcast_trait_ref| { - this.probe(|this, _| { + self.infcx.probe(|_| { let upcast_trait_ref = upcast_trait_ref.clone(); - this.match_poly_trait_ref(obligation, upcast_trait_ref) + self.match_poly_trait_ref(obligation, upcast_trait_ref) .is_ok() }) }) @@ -2671,20 +2652,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // binder moved -\ let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/ - self.in_snapshot(|this, snapshot| { - let (skol_ty, placeholder_map) = this.infcx() + self.infcx.in_snapshot(|snapshot| { + let (skol_ty, placeholder_map) = self.infcx .replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations, } = project::normalize_with_depth( - this, + self, param_env, cause.clone(), recursion_depth, &skol_ty, ); - let skol_obligation = this.tcx().predicate_for_trait_def( + let skol_obligation = self.tcx().predicate_for_trait_def( param_env, cause.clone(), trait_def_id, @@ -2693,7 +2674,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[], ); obligations.push(skol_obligation); - this.infcx() + self.infcx .plug_leaks(placeholder_map, snapshot, obligations) }) }) @@ -2785,9 +2766,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.in_snapshot(|this, snapshot| { + self.infcx.in_snapshot(|snapshot| { let result = - this.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.match_projection_obligation_against_definition_bounds(obligation, snapshot); assert!(result); }) } @@ -2904,12 +2885,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { nested, ); - let trait_obligations: Vec<PredicateObligation<'_>> = self.in_snapshot(|this, snapshot| { + let trait_obligations: Vec<PredicateObligation<'_>> = self.infcx.in_snapshot(|snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, placeholder_map) = this.infcx() + let (trait_ref, placeholder_map) = self.infcx .replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); - this.impl_or_trait_obligations( + self.impl_or_trait_obligations( cause, obligation.recursion_depth + 1, obligation.param_env, @@ -2941,11 +2922,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.in_snapshot(|this, snapshot| { - let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.in_snapshot(|snapshot| { + let (substs, placeholder_map) = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); - this.vtable_impl( + self.vtable_impl( impl_def_id, substs, cause, @@ -3108,14 +3089,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, alias_def_id ); - self.in_snapshot(|this, snapshot| { - let (predicate, placeholder_map) = this.infcx() + self.infcx.in_snapshot(|snapshot| { + let (predicate, placeholder_map) = self.infcx .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let substs = trait_ref.substs; - let trait_obligations = this.impl_or_trait_obligations( + let trait_obligations = self.impl_or_trait_obligations( obligation.cause.clone(), obligation.recursion_depth, obligation.param_env, From 89ad5728be075ec528650ae73aa42dd225b05679 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Thu, 20 Sep 2018 13:56:11 -0400 Subject: [PATCH 095/124] make evaluation track whether outlives relationships mattered Previously, evaluation ignored outlives relationships. Since we using evaluation to skip the "normal" trait selection (which enforces outlives relationships) this led to incorrect results in some cases. --- src/librustc/infer/mod.rs | 2 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/mod.rs | 22 ++-- src/librustc/traits/object_safety.rs | 2 +- .../traits/query/evaluate_obligation.rs | 19 ++- src/librustc/traits/select.rs | 123 +++++------------- src/librustc/ty/util.rs | 36 ++--- src/librustc_typeck/check/cast.rs | 8 +- src/test/ui/hrtb/hrtb-cache-issue-54302.rs | 24 ++++ .../ui/hrtb/hrtb-cache-issue-54302.stderr | 17 +++ 10 files changed, 129 insertions(+), 126 deletions(-) create mode 100644 src/test/ui/hrtb/hrtb-cache-issue-54302.rs create mode 100644 src/test/ui/hrtb/hrtb-cache-issue-54302.stderr diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c000e3aa013f8..2eb9f1d678433 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1455,7 +1455,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span) + !traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) } /// Obtains the latest type of the given closure; this may be a diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 556b97dc9bcf1..219e971b3c927 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -282,7 +282,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, if data.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - if self.selcx.infcx().predicate_must_hold(&obligation) { + if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) { debug!("selecting trait `{:?}` at depth {} evaluated to holds", data, obligation.recursion_depth); return ProcessResult::Changed(vec![]) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 49bd04782b28e..0377b98d3f863 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -628,14 +628,14 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). -pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - span: Span) --> bool -{ - debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", +pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + span: Span, +) -> bool { + debug!("type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", ty, infcx.tcx.item_path_str(def_id)); @@ -650,7 +650,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx predicate: trait_ref.to_predicate(), }; - let result = infcx.predicate_must_hold(&obligation); + let result = infcx.predicate_must_hold_modulo_regions(&obligation); debug!("type_known_to_meet_ty={:?} bound={} => {:?}", ty, infcx.tcx.item_path_str(def_id), result); @@ -677,13 +677,13 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx // assume it is move; linear is always ok. match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { - debug!("type_known_to_meet_bound: ty={:?} bound={} success", + debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", ty, infcx.tcx.item_path_str(def_id)); true } Err(e) => { - debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}", + debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", ty, infcx.tcx.item_path_str(def_id), e); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1554afdeefdaf..31342c250e2bd 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -568,7 +568,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { self.infer_ctxt().enter(|ref infcx| { // the receiver is dispatchable iff the obligation holds - infcx.predicate_must_hold(&obligation) + infcx.predicate_must_hold_modulo_regions(&obligation) }) } diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 4c1d65c46c56f..fdae7d833734e 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -16,11 +16,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// Evaluates whether the predicate can be satisfied in the given /// `ParamEnv`, and returns `false` if not certain. However, this is /// not entirely accurate if inference variables are involved. - pub fn predicate_must_hold( + /// + /// This version may conservatively fail when outlives obligations + /// are required. + pub fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, ) -> bool { - self.evaluate_obligation_no_overflow(obligation) == EvaluationResult::EvaluatedToOk + self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions() + } + + /// Evaluates whether the predicate can be satisfied in the given + /// `ParamEnv`, and returns `false` if not certain. However, this is + /// not entirely accurate if inference variables are involved. + /// + /// This version ignores all outlives constraints. + pub fn predicate_must_hold_modulo_regions( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool { + self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions() } /// Evaluate a given predicate, capturing overflow and propagating it back. diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e7c01df3dca0a..6b4c3469acd5b 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -327,7 +327,8 @@ enum BuiltinImplConditions<'tcx> { /// evaluations. /// /// The evaluation results are ordered: -/// - `EvaluatedToOk` implies `EvaluatedToAmbig` implies `EvaluatedToUnknown` +/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions` +/// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown` /// - `EvaluatedToErr` implies `EvaluatedToRecur` /// - the "union" of evaluation results is equal to their maximum - /// all the "potential success" candidates can potentially succeed, @@ -336,6 +337,8 @@ enum BuiltinImplConditions<'tcx> { pub enum EvaluationResult { /// Evaluation successful EvaluatedToOk, + /// Evaluation successful, but there were unevaluated region obligations + EvaluatedToOkModuloRegions, /// Evaluation is known to be ambiguous - it *might* hold for some /// assignment of inference variables, but it might not. /// @@ -399,9 +402,23 @@ pub enum EvaluationResult { } impl EvaluationResult { + /// True if this evaluation result is known to apply, even + /// considering outlives constraints. + pub fn must_apply_considering_regions(self) -> bool { + self == EvaluatedToOk + } + + /// True if this evaluation result is known to apply, ignoring + /// outlives constraints. + pub fn must_apply_modulo_regions(self) -> bool { + self <= EvaluatedToOkModuloRegions + } + pub fn may_apply(self) -> bool { match self { - EvaluatedToOk | EvaluatedToAmbig | EvaluatedToUnknown => true, + EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => { + true + } EvaluatedToErr | EvaluatedToRecur => false, } @@ -411,13 +428,14 @@ impl EvaluationResult { match self { EvaluatedToUnknown | EvaluatedToRecur => true, - EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr => false, + EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false, } } } impl_stable_hash_for!(enum self::EvaluationResult { EvaluatedToOk, + EvaluatedToOkModuloRegions, EvaluatedToAmbig, EvaluatedToUnknown, EvaluatedToRecur, @@ -686,92 +704,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { None => Ok(EvaluatedToAmbig), }, - ty::Predicate::TypeOutlives(ref binder) => { - assert!(!binder.has_escaping_bound_vars()); - // Check if the type has higher-ranked vars. - if binder.skip_binder().0.has_escaping_bound_vars() { - // If so, this obligation is an error (for now). Eventually we should be - // able to support additional cases here, like `for<'a> &'a str: 'a`. - - // NOTE: this hack is implemented in both trait fulfillment and - // evaluation. If you fix it in one place, make sure you fix it - // in the other. - - // We don't want to allow this sort of reasoning in intercrate - // mode, for backwards-compatibility reasons. - if self.intercrate.is_some() { - Ok(EvaluatedToAmbig) - } else { - Ok(EvaluatedToErr) - } - } else { - // If the type has no late bound vars, then if we assign all - // the inference variables in it to be 'static, then the type - // will be 'static itself. - // - // Therefore, `staticize(T): 'a` holds for any `'a`, so this - // obligation is fulfilled. Because evaluation works with - // staticized types (yes I know this is involved with #21974), - // we are 100% OK here. - Ok(EvaluatedToOk) - } - } - - ty::Predicate::RegionOutlives(ref binder) => { - let ty::OutlivesPredicate(r_a, r_b) = binder.skip_binder(); - - if r_a == r_b { - // for<'a> 'a: 'a. OK - Ok(EvaluatedToOk) - } else if **r_a == ty::ReStatic { - // 'static: 'x always holds. - // - // This special case is handled somewhat inconsistently - if we - // have an inference variable that is supposed to be equal to - // `'static`, then we don't allow it to be equated to an LBR, - // but if we have a literal `'static`, then we *do*. - // - // This is actually consistent with how our region inference works. - // - // It would appear that this sort of inconsistency would - // cause "instability" problems with evaluation caching. However, - // evaluation caching is only for trait predicates, and when - // trait predicates create nested obligations, they contain - // inference variables for all the regions in the trait - the - // only way this codepath can be reached from trait predicate - // evaluation is when the user typed an explicit `where 'static: 'a` - // lifetime bound (in which case we want to return EvaluatedToOk). - // - // If we ever want to handle inference variables that might be - // equatable with ReStatic, we need to make sure we are not confused by - // technically-allowed-by-RFC-447-but-probably-should-not-be - // impls such as - // ```Rust - // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's - // ``` - Ok(EvaluatedToOk) - } else if r_a.is_late_bound() || r_b.is_late_bound() { - // There is no current way to prove `for<'a> 'a: 'x` - // unless `'a = 'x`, because there are no bounds involving - // lifetimes. - - // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x` - // to be `'static`. However, this is not currently done by type - // inference unless `'x` is literally ReStatic. See the comment - // above. - - // We don't want to allow this sort of reasoning in intercrate - // mode, for backwards-compatibility reasons. - if self.intercrate.is_some() { - Ok(EvaluatedToAmbig) - } else { - Ok(EvaluatedToErr) - } - } else { - // Relating 2 inference variable regions. These will - // always hold if our query is "staticized". - Ok(EvaluatedToOk) - } + ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => { + // we do not consider region relationships when + // evaluating trait matches + Ok(EvaluatedToOkModuloRegions) } ty::Predicate::ObjectSafe(trait_def_id) => { @@ -985,6 +921,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); + // Subtle: when checking for a coinductive cycle, we do + // not compare using the "freshened trait refs" (which + // have erased regions) but rather the fully explicit + // trait refs. This is important because it's only a cycle + // if the regions match exactly. let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { @@ -2324,7 +2265,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // See if we can toss out `victim` based on specialization. // This requires us to know *for sure* that the `other` impl applies // i.e., EvaluatedToOk: - if other.evaluation == EvaluatedToOk { + if other.evaluation.must_apply_modulo_regions() { match victim.candidate { ImplCandidate(victim_def) => { let tcx = self.tcx().global_tcx(); @@ -2351,7 +2292,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ParamCandidate(ref cand) => { // Prefer these to a global where-clause bound // (see issue #50825) - is_global(cand) && other.evaluation == EvaluatedToOk + is_global(cand) && other.evaluation.must_apply_modulo_regions() } _ => false, } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1d30ccb87b5d8..0fa4c98be6370 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -851,11 +851,13 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -865,11 +867,13 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -879,11 +883,13 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6ad707e3d2c78..9d418704f487d 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return Err(ErrorReported); } - if self.type_is_known_to_be_sized(t, span) { + if self.type_is_known_to_be_sized_modulo_regions(t, span) { return Ok(Some(PointerKind::Thin)); } @@ -397,7 +397,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { self.expr_ty, self.cast_ty); - if !fcx.type_is_known_to_be_sized(self.cast_ty, self.span) { + if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages @@ -618,8 +618,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool { + fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); - traits::type_known_to_meet_bound(self, self.param_env, ty, lang_item, span) + traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.rs b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs new file mode 100644 index 0000000000000..a20d03c7747cd --- /dev/null +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs @@ -0,0 +1,24 @@ +// Regression test for #54302. +// +// We were incorrectly using the "evaluation cache" (which ignored +// region results) to conclude that `&'static str: Deserialize`, even +// though it would require that `for<'de> 'de: 'static`, which is +// clearly false. + +trait Deserialize<'de> {} + +trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {} + +// Based on this impl, `&'static str` only implements Deserialize<'static>. +// It does not implement for<'de> Deserialize<'de>. +impl<'de: 'a, 'a> Deserialize<'de> for &'a str {} + +fn main() { + fn assert_deserialize_owned<T: DeserializeOwned>() {} + assert_deserialize_owned::<&'static str>(); //~ ERROR + + // It correctly does not implement for<'de> Deserialize<'de>. + // fn assert_hrtb<T: for<'de> Deserialize<'de>>() {} + // assert_hrtb::<&'static str>(); +} diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr new file mode 100644 index 0000000000000..061d0e309c500 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -0,0 +1,17 @@ +error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`) + --> $DIR/hrtb-cache-issue-54302.rs:19:5 + | +LL | assert_deserialize_owned::<&'static str>(); //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str` + = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str` +note: required by `main::assert_deserialize_owned` + --> $DIR/hrtb-cache-issue-54302.rs:18:5 + | +LL | fn assert_deserialize_owned<T: DeserializeOwned>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0279`. From 1e89f289427c832f47adb3e2bab733a547db52a8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 16 Oct 2018 05:42:18 -0400 Subject: [PATCH 096/124] introduce ability to detect region constraints from snapshot --- src/librustc/infer/mod.rs | 9 ++++++ src/librustc/infer/region_constraints/mod.rs | 9 ++++++ src/librustc/traits/select.rs | 30 ++++++++++++++------ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 2eb9f1d678433..9a5e707b57d89 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -868,6 +868,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r } + pub fn region_constraints_added_in_snapshot( + &self, + snapshot: &CombinedSnapshot<'a, 'tcx>, + ) -> bool { + self.borrow_region_constraints().region_constraints_added_in_snapshot( + &snapshot.region_constraints_snapshot, + ) + } + pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) { self.borrow_region_constraints().add_given(sub, sup); } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 66ebbe111dbce..89086e66dffbf 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -854,6 +854,15 @@ impl<'tcx> RegionConstraintCollector<'tcx> { debug!("tainted: result={:?}", taint_set); return taint_set.into_set(); } + + pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> bool { + self.undo_log[mark.length..] + .iter() + .any(|&elt| match elt { + AddConstraint(_) => true, + _ => false, + }) + } } impl fmt::Debug for RegionSnapshot { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6b4c3469acd5b..6ba3e54eaca51 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -629,8 +629,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, obligation: &PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - self.infcx.probe(|_| { - self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + self.evaluation_probe(|this| { + this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + }) + } + + fn evaluation_probe( + &mut self, + op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>, + ) -> Result<EvaluationResult, OverflowError> { + self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> { + let result = op(self)?; + if !self.infcx.region_constraints_added_in_snapshot(snapshot) { + Ok(result) + } else { + Ok(result.max(EvaluatedToOkModuloRegions)) + } }) } @@ -988,10 +1002,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate ); - let result = self.infcx.probe(|_| { + let result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); - match self.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => self.evaluate_predicates_recursively( + match this.confirm_candidate(stack.obligation, candidate) { + Ok(selection) => this.evaluate_predicates_recursively( stack.list(), selection.nested_obligations().iter(), ), @@ -1775,10 +1789,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - self.infcx.probe(|_| { - match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { + self.evaluation_probe(|this| { + match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { - self.evaluate_predicates_recursively(stack.list(), obligations.iter()) + this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => Ok(EvaluatedToErr), } From 9e8fa85e2c3c01c16479fec10b75bd4afd8dbb9a Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Thu, 27 Dec 2018 10:22:55 -0500 Subject: [PATCH 097/124] select.rs: unsizing coercion should use a subtype When we coerce `dyn Foo` to `dyn Bar`, that is OK as long as `Foo` is usable in all contexts where `Bar` is usable (hence using the source must be a subtype of the target). This is needed for the universe-based code to handle `old-lub-glb-object`; that test used to work sort of by accident before with the old code. --- src/librustc/traits/select.rs | 4 ++-- src/test/ui/lub-glb/old-lub-glb-object.rs | 2 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 14 ++++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6ba3e54eaca51..2576578f4c294 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3268,10 +3268,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ); tcx.mk_existential_predicates(iter) }); - let new_trait = tcx.mk_dynamic(existential_predicates, r_b); + let source_trait = tcx.mk_dynamic(existential_predicates, r_b); let InferOk { obligations, .. } = self.infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_trait) + .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 309f2d0ea7663..132df608af71a 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -7,7 +7,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { //~ ERROR incompatible types + let z = match 22 { //~ ERROR cannot infer 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 243414c19c01e..3a7478b73b85a 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,17 +1,19 @@ error[E0308]: match arms have incompatible types --> $DIR/old-lub-glb-object.rs:10:13 | -LL | let z = match 22 { //~ ERROR incompatible types +LL | let z = match 22 { //~ ERROR cannot infer | _____________^ LL | | 0 => x, LL | | _ => y, - | | - match arm with an incompatible type LL | | }; - | |_____^ expected bound lifetime parameter 'a, found concrete lifetime + | |_____^ | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found type `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U5, name: BrNamed(crate0:DefIndex(1:11), 'a) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U5, name: BrNamed(crate0:DefIndex(1:12), 'b) })... + = note: ...so that the types are compatible: + expected dyn for<'a, 'b> Foo<&'a u8, &'b u8> + found dyn for<'a> Foo<&'a u8, &'a u8> error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. From 254d1a4280aecffe88585a5421ca5d3a5bbbe058 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Thu, 27 Dec 2018 10:23:02 -0500 Subject: [PATCH 098/124] WIP: wfcheck ability to detect --- src/librustc_typeck/check/wfcheck.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 65539d3b10709..53e44d53e6a9b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -873,7 +873,7 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>( trait_ref.to_predicate() ); - if !fcx.predicate_must_hold(&obligation) { + if !fcx.predicate_must_hold_modulo_regions(&obligation) { debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait", receiver_ty); return false From b46812b065d8d68b20e0081bbca592650d128ebc Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 7 Sep 2018 20:11:23 -0400 Subject: [PATCH 099/124] universe transition Remove the leak-check and its associated machinery. Replace with making the solver aware of universes. --- src/librustc/infer/higher_ranked/mod.rs | 507 ++---------------- .../infer/lexical_region_resolve/mod.rs | 41 +- src/librustc/infer/mod.rs | 86 +-- src/librustc/infer/region_constraints/mod.rs | 31 -- .../infer/region_constraints/taint.rs | 85 --- src/librustc/traits/auto_trait.rs | 8 +- src/librustc/traits/error_reporting.rs | 9 +- src/librustc/traits/fulfill.rs | 6 +- src/librustc/traits/project.rs | 48 +- src/librustc/traits/select.rs | 122 ++--- 10 files changed, 144 insertions(+), 799 deletions(-) delete mode 100644 src/librustc/infer/region_constraints/taint.rs diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 3a3a21d0f1d4a..709e8c0ba9b24 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -1,31 +1,23 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use super::{CombinedSnapshot, - InferCtxt, - HigherRankedType, - SubregionOrigin, - PlaceholderMap}; use super::combine::CombineFields; -use super::region_constraints::{TaintDirections}; +use super::{HigherRankedType, InferCtxt, PlaceholderMap}; -use ty::{self, TyCtxt, Binder, TypeFoldable}; -use ty::error::TypeError; use ty::relate::{Relate, RelateResult, TypeRelation}; -use syntax_pos::Span; -use util::nodemap::{FxHashMap, FxHashSet}; - -pub struct HrMatchResult<U> { - pub value: U, -} +use ty::{self, Binder, TypeFoldable}; impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { - pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool) - -> RelateResult<'tcx, Binder<T>> - where T: Relate<'tcx> + pub fn higher_ranked_sub<T>( + &mut self, + a: &Binder<T>, + b: &Binder<T>, + a_is_expected: bool, + ) -> RelateResult<'tcx, Binder<T>> + where + T: Relate<'tcx>, { - debug!("higher_ranked_sub(a={:?}, b={:?})", - a, b); + debug!("higher_ranked_sub(a={:?}, b={:?})", a, b); // Rather than checking the subtype relationship between `a` and `b` // as-is, we need to do some extra work here in order to make sure @@ -35,279 +27,37 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // please see the large comment at the end of the file in the (inlined) module // `doc`. - // Start a snapshot so we can examine "all bindings that were - // created as part of this type comparison". - return self.infcx.commit_if_ok(|snapshot| { - let span = self.trace.cause.span; - - // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. - let (b_prime, placeholder_map) = - self.infcx.replace_bound_vars_with_placeholders(b); - - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other pre-existing region variables -- can name - // the placeholders. - let (a_prime, _) = self.infcx.replace_bound_vars_with_fresh_vars( - span, - HigherRankedType, - a - ); - - debug!("a_prime={:?}", a_prime); - debug!("b_prime={:?}", b_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - - // Presuming type comparison succeeds, we need to check - // that the placeholder regions do not "leak". - self.infcx.leak_check(!a_is_expected, span, &placeholder_map, snapshot)?; - - // We are finished with the placeholder regions now so pop - // them off. - self.infcx.pop_placeholders(placeholder_map, snapshot); - - debug!("higher_ranked_sub: OK result={:?}", result); - - Ok(ty::Binder::bind(result)) - }); - } - - /// The value consists of a pair `(t, u)` where `t` is the - /// *matcher* and `u` is a *value*. The idea is to find a - /// substitution `S` such that `S(t) == b`, and then return - /// `S(u)`. In other words, find values for the late-bound regions - /// in `a` that can make `t == b` and then replace the LBR in `u` - /// with those values. - /// - /// This routine is (as of this writing) used in trait matching, - /// particularly projection. - /// - /// NB. It should not happen that there are LBR appearing in `U` - /// that do not appear in `T`. If that happens, those regions are - /// unconstrained, and this routine replaces them with `'static`. - pub fn higher_ranked_match<T, U>(&mut self, - a_pair: &Binder<(T, U)>, - b_match: &T, - a_is_expected: bool) - -> RelateResult<'tcx, HrMatchResult<U>> - where T: Relate<'tcx>, - U: TypeFoldable<'tcx> - { - debug!("higher_ranked_match(a={:?}, b={:?})", - a_pair, b_match); - - // Start a snapshot so we can examine "all bindings that were - // created as part of this type comparison". - return self.infcx.commit_if_ok(|snapshot| { - // First, we instantiate each bound region in the matcher - // with a placeholder region. - let ((a_match, a_value), placeholder_map) = - self.infcx.replace_bound_vars_with_placeholders(a_pair); + let span = self.trace.cause.span; - debug!("higher_ranked_match: a_match={:?}", a_match); - debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map); + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); - // Equate types now that bound regions have been replaced. - self.equate(a_is_expected).relate(&a_match, &b_match)?; + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other pre-existing region variables -- can name + // the placeholders. + let (a_prime, _) = + self.infcx + .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); - // Map each placeholder region to a vector of other regions that it - // must be equated with. (Note that this vector may include other - // placeholder regions from `placeholder_map`.) - let placeholder_resolution_map: FxHashMap<_, _> = - placeholder_map - .iter() - .map(|(&br, &placeholder)| { - let tainted_regions = - self.infcx.tainted_regions(snapshot, - placeholder, - TaintDirections::incoming()); // [1] + debug!("a_prime={:?}", a_prime); + debug!("b_prime={:?}", b_prime); - // [1] this routine executes after the placeholder - // regions have been *equated* with something - // else, so examining the incoming edges ought to - // be enough to collect all constraints + // Compare types now that bound regions have been replaced. + let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - (placeholder, (br, tainted_regions)) - }) - .collect(); + debug!("higher_ranked_sub: OK result={:?}", result); - // For each placeholder region, pick a representative -- which can - // be any region from the sets above, except for other members of - // `placeholder_map`. There should always be a representative if things - // are properly well-formed. - let placeholder_representatives: FxHashMap<_, _> = - placeholder_resolution_map - .iter() - .map(|(&placeholder, &(_, ref regions))| { - let representative = - regions.iter() - .filter(|&&r| !placeholder_resolution_map.contains_key(r)) - .cloned() - .next() - .unwrap_or_else(|| { - bug!("no representative region for `{:?}` in `{:?}`", - placeholder, regions) - }); - - (placeholder, representative) - }) - .collect(); - - // Equate all the members of each placeholder set with the - // representative. - for (placeholder, &(_br, ref regions)) in &placeholder_resolution_map { - let representative = &placeholder_representatives[placeholder]; - debug!("higher_ranked_match: \ - placeholder={:?} representative={:?} regions={:?}", - placeholder, representative, regions); - for region in regions.iter() - .filter(|&r| !placeholder_resolution_map.contains_key(r)) - .filter(|&r| r != representative) - { - let origin = SubregionOrigin::Subtype(self.trace.clone()); - self.infcx.borrow_region_constraints() - .make_eqregion(origin, - *representative, - *region); - } - } - - // Replace the placeholder regions appearing in value with - // their representatives - let a_value = - fold_regions_in( - self.tcx(), - &a_value, - |r, _| placeholder_representatives.get(&r).cloned().unwrap_or(r)); - - debug!("higher_ranked_match: value={:?}", a_value); - - // We are now done with these placeholder variables. - self.infcx.pop_placeholders(placeholder_map, snapshot); - - Ok(HrMatchResult { value: a_value }) - }); + Ok(ty::Binder::bind(result)) } } -fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - unbound_value: &T, - mut fldr: F) - -> T - where T: TypeFoldable<'tcx>, - F: FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, -{ - tcx.fold_regions(unbound_value, &mut false, |region, current_depth| { - // we should only be encountering "escaping" late-bound regions here, - // because the ones at the current level should have been replaced - // with fresh variables - assert!(match *region { - ty::ReLateBound(..) => false, - _ => true - }); - - fldr(region, current_depth) - }) -} - impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn tainted_regions(&self, - snapshot: &CombinedSnapshot<'a, 'tcx>, - r: ty::Region<'tcx>, - directions: TaintDirections) - -> FxHashSet<ty::Region<'tcx>> { - self.borrow_region_constraints().tainted( - self.tcx, - &snapshot.region_constraints_snapshot, - r, - directions) - } - - fn region_vars_confined_to_snapshot(&self, - snapshot: &CombinedSnapshot<'a, 'tcx>) - -> Vec<ty::RegionVid> - { - /*! - * Returns the set of region variables that do not affect any - * types/regions which existed before `snapshot` was - * started. This is used in the sub/lub/glb computations. The - * idea here is that when we are computing lub/glb of two - * regions, we sometimes create intermediate region variables. - * Those region variables may touch some of the placeholder or - * other "forbidden" regions we created to replace bound - * regions, but they don't really represent an "external" - * constraint. - * - * However, sometimes fresh variables are created for other - * purposes too, and those *may* represent an external - * constraint. In particular, when a type variable is - * instantiated, we create region variables for all the - * regions that appear within, and if that type variable - * pre-existed the snapshot, then those region variables - * represent external constraints. - * - * An example appears in the unit test - * `sub_free_bound_false_infer`. In this test, we want to - * know whether - * - * ```rust - * fn(_#0t) <: for<'a> fn(&'a int) - * ``` - * - * Note that the subtype has a type variable. Because the type - * variable can't be instantiated with a region that is bound - * in the fn signature, this comparison ought to fail. But if - * we're not careful, it will succeed. - * - * The reason is that when we walk through the subtyping - * algorithm, we begin by replacing `'a` with a placeholder - * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This - * can be made true by unifying `_#0t` with `&'1 int`. In the - * process, we create a fresh variable for the placeholder - * region, `'$2`, and hence we have that `_#0t == &'$2 - * int`. However, because `'$2` was created during the sub - * computation, if we're not careful we will erroneously - * assume it is one of the transient region variables - * representing a lub/glb internally. Not good. - * - * To prevent this, we check for type variables which were - * unified during the snapshot, and say that any region - * variable created during the snapshot but which finds its - * way into a type variable is considered to "escape" the - * snapshot. - */ - - let mut region_vars = - self.borrow_region_constraints().vars_created_since_snapshot( - &snapshot.region_constraints_snapshot); - - let escaping_types = - self.type_variables.borrow_mut().types_escaping_snapshot(&snapshot.type_snapshot); - - let mut escaping_region_vars = FxHashSet::default(); - for ty in &escaping_types { - self.tcx.collect_regions(ty, &mut escaping_region_vars); - } - - region_vars.retain(|®ion_vid| { - let r = ty::ReVar(region_vid); - !escaping_region_vars.contains(&r) - }); - - debug!("region_vars_confined_to_snapshot: region_vars={:?} escaping_types={:?}", - region_vars, - escaping_types); - - region_vars - } - /// Replace all regions (resp. types) bound by `binder` with placeholder /// regions (resp. types) and return a map indicating which bound-region - /// was replaced with what placeholder region. This is the first step of - /// checking subtyping when higher-ranked things are involved. + /// placeholder region. This is the first step of checking subtyping + /// when higher-ranked things are involved. /// /// **Important:** you must call this function from within a snapshot. /// Moreover, before committing the snapshot, you must eventually call @@ -354,201 +104,4 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } - - /// Searches the region constraints created since `snapshot` was started - /// and checks to determine whether any of the placeholder regions created - /// in `placeholder_map` would "escape" -- meaning that they are related to - /// other regions in some way. If so, the higher-ranked subtyping doesn't - /// hold. See `README.md` for more details. - pub fn leak_check(&self, - overly_polymorphic: bool, - _span: Span, - placeholder_map: &PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>) - -> RelateResult<'tcx, ()> - { - debug!("leak_check: placeholder_map={:?}", - placeholder_map); - - // If the user gave `-Zno-leak-check`, then skip the leak - // check completely. This is wildly unsound and also not - // unlikely to cause an ICE or two. It is intended for use - // only during a transition period, in which the MIR typeck - // uses the "universe-style" check, and the rest of typeck - // uses the more conservative leak check. Since the leak - // check is more conservative, we can't test the - // universe-style check without disabling it. - if self.tcx.sess.opts.debugging_opts.no_leak_check { - return Ok(()); - } - - let new_vars = self.region_vars_confined_to_snapshot(snapshot); - for (&placeholder_br, &placeholder) in placeholder_map { - // The inputs to a placeholder variable can only - // be itself or other new variables. - let incoming_taints = self.tainted_regions(snapshot, - placeholder, - TaintDirections::both()); - for &tainted_region in &incoming_taints { - // Each placeholder should only be relatable to itself - // or new variables: - match *tainted_region { - ty::ReVar(vid) => { - if new_vars.contains(&vid) { - continue; - } - } - _ => { - if tainted_region == placeholder { continue; } - } - }; - - debug!("{:?} (which replaced {:?}) is tainted by {:?}", - placeholder, - placeholder_br, - tainted_region); - - return Err(if overly_polymorphic { - debug!("Overly polymorphic!"); - TypeError::RegionsOverlyPolymorphic(placeholder_br, tainted_region) - } else { - debug!("Not as polymorphic!"); - TypeError::RegionsInsufficientlyPolymorphic(placeholder_br, tainted_region) - }) - } - } - - Ok(()) - } - - /// This code converts from placeholder regions back to late-bound - /// regions. It works by replacing each region in the taint set of a - /// placeholder region with a bound-region. The bound region will be bound - /// by the outer-most binder in `value`; the caller must ensure that there is - /// such a binder and it is the right place. - /// - /// This routine is only intended to be used when the leak-check has - /// passed; currently, it's used in the trait matching code to create - /// a set of nested obligations from an impl that matches against - /// something higher-ranked. More details can be found in - /// `librustc/middle/traits/README.md`. - /// - /// As a brief example, consider the obligation `for<'a> Fn(&'a int) - /// -> &'a int`, and the impl: - /// - /// impl<A,R> Fn<A,R> for SomethingOrOther - /// where A : Clone - /// { ... } - /// - /// Here we will have replaced `'a` with a placeholder region - /// `'0`. This means that our substitution will be `{A=>&'0 - /// int, R=>&'0 int}`. - /// - /// When we apply the substitution to the bounds, we will wind up with - /// `&'0 int : Clone` as a predicate. As a last step, we then go and - /// replace `'0` with a late-bound region `'a`. The depth is matched - /// to the depth of the predicate, in this case 1, so that the final - /// predicate is `for<'a> &'a int : Clone`. - pub fn plug_leaks<T>(&self, - placeholder_map: PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>, - value: T) -> T - where T : TypeFoldable<'tcx> - { - debug!("plug_leaks(placeholder_map={:?}, value={:?})", - placeholder_map, - value); - - if placeholder_map.is_empty() { - return value; - } - - // Compute a mapping from the "taint set" of each placeholder - // region back to the `ty::BoundRegion` that it originally - // represented. Because `leak_check` passed, we know that - // these taint sets are mutually disjoint. - let inv_placeholder_map: FxHashMap<ty::Region<'tcx>, ty::BoundRegion> = - placeholder_map - .iter() - .flat_map(|(&placeholder_br, &placeholder)| { - self.tainted_regions(snapshot, placeholder, TaintDirections::both()) - .into_iter() - .map(move |tainted_region| (tainted_region, placeholder_br)) - }) - .collect(); - - debug!("plug_leaks: inv_placeholder_map={:?}", - inv_placeholder_map); - - // Remove any instantiated type variables from `value`; those can hide - // references to regions from the `fold_regions` code below. - let value = self.resolve_type_vars_if_possible(&value); - - // Map any placeholder byproducts back to a late-bound - // region. Put that late-bound region at whatever the outermost - // binder is that we encountered in `value`. The caller is - // responsible for ensuring that (a) `value` contains at least one - // binder and (b) that binder is the one we want to use. - let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| { - match inv_placeholder_map.get(&r) { - None => r, - Some(br) => { - // It is the responsibility of the caller to ensure - // that each placeholder region appears within a - // binder. In practice, this routine is only used by - // trait checking, and all of the placeholder regions - // appear inside predicates, which always have - // binders, so this assert is satisfied. - assert!(current_depth > ty::INNERMOST); - - // since leak-check passed, this placeholder region - // should only have incoming edges from variables - // (which ought not to escape the snapshot, but we - // don't check that) or itself - assert!( - match *r { - ty::ReVar(_) => true, - ty::RePlaceholder(index) => index.name == *br, - _ => false, - }, - "leak-check would have us replace {:?} with {:?}", - r, br); - - self.tcx.mk_region(ty::ReLateBound( - current_depth.shifted_out(1), - br.clone(), - )) - } - } - }); - - self.pop_placeholders(placeholder_map, snapshot); - - debug!("plug_leaks: result={:?}", result); - - result - } - - /// Pops the placeholder regions found in `placeholder_map` from the region - /// inference context. Whenever you create placeholder regions via - /// `replace_bound_vars_with_placeholders`, they must be popped before you - /// commit the enclosing snapshot (if you do not commit, e.g., within a - /// probe or as a result of an error, then this is not necessary, as - /// popping happens as part of the rollback). - /// - /// Note: popping also occurs implicitly as part of `leak_check`. - pub fn pop_placeholders( - &self, - placeholder_map: PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>, - ) { - debug!("pop_placeholders({:?})", placeholder_map); - let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect(); - self.borrow_region_constraints().pop_placeholders(&placeholder_regions); - self.universe.set(snapshot.universe); - if !placeholder_map.is_empty() { - self.projection_cache.borrow_mut().rollback_placeholder( - &snapshot.projection_cache_snapshot); - } - } } diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index de64800ee8d35..bbab17f951659 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -215,23 +215,41 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { ) -> bool { debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data); - // Check if this relationship is implied by a given. match *a_region { + // Check if this relationship is implied by a given. ty::ReEarlyBound(_) | ty::ReFree(_) => if self.data.givens.contains(&(a_region, b_vid)) { debug!("given"); return false; }, + _ => {} } + match *b_data { VarValue::Value(cur_region) => { - let lub = self.lub_concrete_regions(a_region, cur_region); + let mut lub = self.lub_concrete_regions(a_region, cur_region); if lub == cur_region { return false; } + // Watch out for `'b: !1` relationships, where the + // universe of `'b` can't name the placeholder `!1`. In + // that case, we have to grow `'b` to be `'static` for the + // relationship to hold. This is obviously a kind of sub-optimal + // choice -- in the future, when we incorporate a knowledge + // of the parameter environment, we might be able to find a + // tighter bound than `'static`. + // + // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.) + let b_universe = self.var_infos[b_vid].universe; + if let ty::RePlaceholder(p) = lub { + if b_universe.cannot_name(p.universe) { + lub = self.tcx().types.re_static; + } + } + debug!( "Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub @@ -554,10 +572,22 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { lower_bounds.sort_by_key(region_order_key); upper_bounds.sort_by_key(region_order_key); + let node_universe = self.var_infos[node_idx].universe; + for lower_bound in &lower_bounds { + let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region { + if node_universe.cannot_name(p.universe) { + self.tcx().types.re_static + } else { + lower_bound.region + } + } else { + lower_bound.region + }; + for upper_bound in &upper_bounds { if !self.region_rels - .is_subregion_of(lower_bound.region, upper_bound.region) + .is_subregion_of(effective_lower_bound, upper_bound.region) { let origin = self.var_infos[node_idx].origin.clone(); debug!( @@ -580,9 +610,10 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { span_bug!( self.var_infos[node_idx].origin.span(), "collect_error_for_expanding_node() could not find \ - error for var {:?}, lower_bounds={:?}, \ - upper_bounds={:?}", + error for var {:?} in universe {:?}, lower_bounds={:#?}, \ + upper_bounds={:#?}", node_idx, + node_universe, lower_bounds, upper_bounds ); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 9a5e707b57d89..3b9affa6ffb50 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -32,7 +32,6 @@ use ty::{FloatVid, IntVid, TyVid}; use util::nodemap::FxHashMap; use self::combine::CombineFields; -use self::higher_ranked::HrMatchResult; use self::lexical_region_resolve::LexicalRegionResolutions; use self::outlives::env::OutlivesEnvironment; use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; @@ -948,39 +947,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - Some(self.commit_if_ok(|snapshot| { - let ( - ty::SubtypePredicate { - a_is_expected, - a, - b, - }, - placeholder_map, - ) = self.replace_bound_vars_with_placeholders(predicate); + let ( + ty::SubtypePredicate { + a_is_expected, + a, + b, + }, + _, + ) = self.replace_bound_vars_with_placeholders(predicate); - let cause_span = cause.span; - let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, cause_span, &placeholder_map, snapshot)?; - self.pop_placeholders(placeholder_map, snapshot); - Ok(ok.unit()) - })) + Some( + self.at(cause, param_env) + .sub_exp(a_is_expected, a, b) + .map(|ok| ok.unit()), + ) } pub fn region_outlives_predicate( &self, cause: &traits::ObligationCause<'tcx>, predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, - ) -> UnitResult<'tcx> { - self.commit_if_ok(|snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = - self.replace_bound_vars_with_placeholders(predicate); - let origin = SubregionOrigin::from_obligation_cause(cause, || { - RelateRegionParamBound(cause.span) - }); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, cause.span, &placeholder_map, snapshot)?; - Ok(self.pop_placeholders(placeholder_map, snapshot)) - }) + ) { + let (ty::OutlivesPredicate(r_a, r_b), _) = + self.replace_bound_vars_with_placeholders(predicate); + let origin = + SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` } pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { @@ -1389,46 +1381,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.replace_bound_vars(value, fld_r, fld_t) } - /// Given a higher-ranked projection predicate like: - /// - /// for<'a> <T as Fn<&'a u32>>::Output = &'a u32 - /// - /// and a target trait-ref like: - /// - /// <T as Fn<&'x u32>> - /// - /// find a substitution `S` for the higher-ranked regions (here, - /// `['a => 'x]`) such that the predicate matches the trait-ref, - /// and then return the value (here, `&'a u32`) but with the - /// substitution applied (hence, `&'x u32`). - /// - /// See `higher_ranked_match` in `higher_ranked/mod.rs` for more - /// details. - pub fn match_poly_projection_predicate( - &self, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - match_a: ty::PolyProjectionPredicate<'tcx>, - match_b: ty::TraitRef<'tcx>, - ) -> InferResult<'tcx, HrMatchResult<Ty<'tcx>>> { - let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty)); - let trace = TypeTrace { - cause, - values: TraitRefs(ExpectedFound::new( - true, - match_pair.skip_binder().0, - match_b, - )), - }; - - let mut combine = self.combine_fields(trace, param_env); - let result = combine.higher_ranked_match(&match_pair, &match_b, true)?; - Ok(InferOk { - value: result, - obligations: combine.obligations, - }) - } - /// See `verify_generic_bound` method in `region_constraints` pub fn verify_generic_bound( &self, diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 89086e66dffbf..b29eb67dfa225 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -17,8 +17,6 @@ use ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; -mod taint; - #[derive(Default)] pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. @@ -826,35 +824,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { .collect() } - /// Computes all regions that have been related to `r0` since the - /// mark `mark` was made---`r0` itself will be the first - /// entry. The `directions` parameter controls what kind of - /// relations are considered. For example, one can say that only - /// "incoming" edges to `r0` are desired, in which case one will - /// get the set of regions `{r|r <= r0}`. This is used when - /// checking whether placeholder regions are being improperly - /// related to other regions. - pub fn tainted( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - mark: &RegionSnapshot, - r0: Region<'tcx>, - directions: TaintDirections, - ) -> FxHashSet<ty::Region<'tcx>> { - debug!( - "tainted(mark={:?}, r0={:?}, directions={:?})", - mark, r0, directions - ); - - // `result_set` acts as a worklist: we explore all outgoing - // edges and add any new regions we find to result_set. This - // is not a terribly efficient implementation. - let mut taint_set = taint::TaintSet::new(directions, r0); - taint_set.fixed_point(tcx, &self.undo_log[mark.length..], &self.data.verifys); - debug!("tainted: result={:?}", taint_set); - return taint_set.into_set(); - } - pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> bool { self.undo_log[mark.length..] .iter() diff --git a/src/librustc/infer/region_constraints/taint.rs b/src/librustc/infer/region_constraints/taint.rs deleted file mode 100644 index 6743f37972ae5..0000000000000 --- a/src/librustc/infer/region_constraints/taint.rs +++ /dev/null @@ -1,85 +0,0 @@ -use super::*; - -#[derive(Debug)] -pub(super) struct TaintSet<'tcx> { - directions: TaintDirections, - regions: FxHashSet<ty::Region<'tcx>>, -} - -impl<'tcx> TaintSet<'tcx> { - pub(super) fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { - let mut regions = FxHashSet::default(); - regions.insert(initial_region); - TaintSet { - directions: directions, - regions: regions, - } - } - - pub(super) fn fixed_point( - &mut self, - tcx: TyCtxt<'_, '_, 'tcx>, - undo_log: &[UndoLog<'tcx>], - verifys: &[Verify<'tcx>], - ) { - let mut prev_len = 0; - while prev_len < self.len() { - debug!( - "tainted: prev_len = {:?} new_len = {:?}", - prev_len, - self.len() - ); - - prev_len = self.len(); - - for undo_entry in undo_log { - match undo_entry { - &AddConstraint(Constraint::VarSubVar(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::RegSubVar(a, b)) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::VarSubReg(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), b); - } - &AddConstraint(Constraint::RegSubReg(a, b)) => { - self.add_edge(a, b); - } - &AddGiven(a, b) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddVerify(i) => { - span_bug!( - verifys[i].origin.span(), - "we never add verifications while doing higher-ranked things", - ) - } - &Purged | &AddCombination(..) | &AddVar(..) => {} - } - } - } - } - - pub(super) fn into_set(self) -> FxHashSet<ty::Region<'tcx>> { - self.regions - } - - fn len(&self) -> usize { - self.regions.len() - } - - fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { - if self.directions.incoming { - if self.regions.contains(&target) { - self.regions.insert(source); - } - } - - if self.directions.outgoing { - if self.regions.contains(&source) { - self.regions.insert(target); - } - } - } -} diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index f96c4e9014b36..92004ece26d00 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -771,13 +771,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } &ty::Predicate::RegionOutlives(ref binder) => { - if select - .infcx() - .region_outlives_predicate(&dummy_cause, binder) - .is_err() - { - return false; - } + let () = select.infcx().region_outlives_predicate(&dummy_cause, binder); } &ty::Predicate::TypeOutlives(ref binder) => { match ( diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0e63ef666c75a..21352ac1053a8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -728,12 +728,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) + // These errors should show up as region + // inference failures. + panic!("region outlives {:?} failed", predicate); } ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 219e971b3c927..2e00d4d4b7c3b 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -331,10 +331,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::RegionOutlives(ref binder) => { - match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) { - Ok(()) => ProcessResult::Changed(vec![]), - Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)), - } + let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder); + ProcessResult::Changed(vec![]) } ty::Predicate::TypeOutlives(ref binder) => { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 952b37b89f2d4..732ca70dc78c5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -13,7 +13,7 @@ use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPoin use super::util; use hir::def_id::DefId; -use infer::{InferCtxt, InferOk}; +use infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use infer::type_variable::TypeVariableOrigin; use mir::interpret::ConstValue; use mir::interpret::{GlobalId}; @@ -192,28 +192,12 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = + infcx.commit_if_ok(|_| { + let (placeholder_predicate, _) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); - let skol_obligation = obligation.with(placeholder_predicate); - let r = match project_and_unify_type(selcx, &skol_obligation) { - Ok(result) => { - let span = obligation.cause.span; - match infcx.leak_check(false, span, &placeholder_map, snapshot) { - Ok(()) => Ok(infcx.plug_leaks(placeholder_map, snapshot, result)), - Err(e) => { - debug!("poly_project_and_unify_type: leak check encountered error {:?}", e); - Err(MismatchedProjectionTypes { err: e }) - } - } - } - Err(e) => { - Err(e) - } - }; - - r + let placeholder_obligation = obligation.with(placeholder_predicate); + project_and_unify_type(selcx, &placeholder_obligation) }) } @@ -1443,17 +1427,25 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - poly_projection: ty::PolyProjectionPredicate<'tcx>) + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>) -> Progress<'tcx> { let infcx = selcx.infcx(); - let cause = obligation.cause.clone(); + let cause = &obligation.cause; let param_env = obligation.param_env; - let trait_ref = obligation.predicate.trait_ref(infcx.tcx); - match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) { - Ok(InferOk { value: ty_match, obligations }) => { + + let (cache_entry, _) = + infcx.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + &poly_cache_entry); + + let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); + let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); + match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { + Ok(InferOk { value: _, obligations }) => { Progress { - ty: ty_match.value, + ty: cache_entry.ty, obligations, } } @@ -1463,7 +1455,7 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( "Failed to unify obligation `{:?}` \ with poly_projection `{:?}`: {:?}", obligation, - poly_projection, + poly_cache_entry, e); } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 2576578f4c294..f5e96286d184e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -29,7 +29,7 @@ use super::{ use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; -use infer::{self, InferCtxt, InferOk, TypeFreshener}; +use infer::{InferCtxt, InferOk, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; @@ -44,7 +44,6 @@ use rustc_target::spec::abi::Abi; use std::cmp; use std::fmt; use std::iter; -use std::mem; use std::rc::Rc; use util::nodemap::{FxHashMap, FxHashSet}; @@ -1633,8 +1632,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => return, } - let result = self.infcx.probe(|snapshot| { - self.match_projection_obligation_against_definition_bounds(obligation, snapshot) + let result = self.infcx.probe(|_| { + self.match_projection_obligation_against_definition_bounds(obligation) }); if result { @@ -1645,16 +1644,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (skol_trait_predicate, placeholder_map) = self.infcx() + let (skol_trait_predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ - skol_trait_predicate={:?} placeholder_map={:?}", - skol_trait_predicate, placeholder_map + skol_trait_predicate={:?}", + skol_trait_predicate, ); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { @@ -1691,8 +1689,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound.clone(), skol_trait_predicate.trait_ref.clone(), - &placeholder_map, - snapshot, ) }) }); @@ -1710,12 +1706,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound, skol_trait_predicate.trait_ref.clone(), - &placeholder_map, - snapshot, ); - self.infcx.pop_placeholders(placeholder_map, snapshot); - assert!(result); true } @@ -1727,20 +1719,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, skol_trait_ref: ty::TraitRef<'tcx>, - placeholder_map: &infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); - if self.infcx + self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) - .is_err() - { - return false; - } - - self.infcx - .leak_check(false, obligation.cause.span, placeholder_map, snapshot) .is_ok() } @@ -1942,14 +1925,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|snapshot| { - if let Ok(placeholder_map) = self.match_impl(impl_def_id, obligation, snapshot) + self.infcx.probe(|_| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); - - // N.B., we can safely drop the placeholder map - // since we are in a probe. - mem::drop(placeholder_map); } }); }, @@ -2607,8 +2586,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // binder moved -\ let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/ - self.infcx.in_snapshot(|snapshot| { - let (skol_ty, placeholder_map) = self.infcx + self.infcx.in_snapshot(|_| { + let (skol_ty, _) = self.infcx .replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, @@ -2629,8 +2608,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[], ); obligations.push(skol_obligation); - self.infcx - .plug_leaks(placeholder_map, snapshot, obligations) + obligations }) }) .collect() @@ -2721,9 +2699,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.in_snapshot(|snapshot| { + self.infcx.in_snapshot(|_| { let result = - self.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.match_projection_obligation_against_definition_bounds(obligation); assert!(result); }) } @@ -2840,9 +2818,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { nested, ); - let trait_obligations: Vec<PredicateObligation<'_>> = self.infcx.in_snapshot(|snapshot| { + let trait_obligations: Vec<PredicateObligation<'_>> = self.infcx.in_snapshot(|_| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, placeholder_map) = self.infcx + let (trait_ref, _) = self.infcx .replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); self.impl_or_trait_obligations( @@ -2851,8 +2829,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.param_env, trait_def_id, &trait_ref.substs, - placeholder_map, - snapshot, ) }); @@ -2877,8 +2853,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.in_snapshot(|snapshot| { - let (substs, placeholder_map) = self.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.in_snapshot(|_| { + let substs = self.rematch_impl(impl_def_id, obligation); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); self.vtable_impl( @@ -2887,8 +2863,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cause, obligation.recursion_depth + 1, obligation.param_env, - placeholder_map, - snapshot, ) }) } @@ -2900,12 +2874,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - placeholder_map: infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> { debug!( - "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, placeholder_map={:?})", - impl_def_id, substs, recursion_depth, placeholder_map + "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})", + impl_def_id, substs, recursion_depth, ); let mut impl_obligations = self.impl_or_trait_obligations( @@ -2914,8 +2886,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { param_env, impl_def_id, &substs.value, - placeholder_map, - snapshot, ); debug!( @@ -3044,8 +3014,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, alias_def_id ); - self.infcx.in_snapshot(|snapshot| { - let (predicate, placeholder_map) = self.infcx + self.infcx.in_snapshot(|_| { + let (predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; @@ -3057,8 +3027,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.param_env, trait_def_id, &substs, - placeholder_map, - snapshot, ); debug!( @@ -3473,13 +3441,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, - ) -> ( - Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::PlaceholderMap<'tcx>, - ) { - match self.match_impl(impl_def_id, obligation, snapshot) { - Ok((substs, placeholder_map)) => (substs, placeholder_map), + ) -> Normalized<'tcx, &'tcx Substs<'tcx>> { + match self.match_impl(impl_def_id, obligation) { + Ok(substs) => substs, Err(()) => { bug!( "Impl {:?} was matchable against {:?} but now is not", @@ -3494,14 +3458,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, - ) -> Result< - ( - Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::PlaceholderMap<'tcx>, - ), - (), - > { + ) -> Result<Normalized<'tcx, &'tcx Substs<'tcx>>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); // Before we create the substitutions and everything, first @@ -3511,7 +3468,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } - let (skol_obligation, placeholder_map) = self.infcx() + let (skol_obligation, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; @@ -3543,22 +3500,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = - self.infcx - .leak_check(false, obligation.cause.span, &placeholder_map, snapshot) - { - debug!("match_impl: failed leak check due to `{}`", e); - return Err(()); - } - debug!("match_impl: success impl_substs={:?}", impl_substs); - Ok(( - Normalized { - value: impl_substs, - obligations: nested_obligations, - }, - placeholder_map, - )) + Ok(Normalized { + value: impl_substs, + obligations: nested_obligations, + }) } fn fast_reject_trait_refs( @@ -3714,8 +3660,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, def_id: DefId, // of impl or trait substs: &Substs<'tcx>, // for impl or trait - placeholder_map: infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> Vec<PredicateObligation<'tcx>> { debug!("impl_or_trait_obligations(def_id={:?})", def_id); let tcx = self.tcx(); @@ -3777,8 +3721,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut seen = FxHashSet::default(); predicates.retain(|i| seen.insert(i.clone())); } - self.infcx() - .plug_leaks(placeholder_map, snapshot, predicates) + + predicates } } From 8165541fd295997cc62c96bae72ada4637133bc2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 30 Oct 2018 16:38:50 -0400 Subject: [PATCH 100/124] add tests exercising `exists<'a> { forall<'b> { .. } }` pattern Amazingly, this scenario was not tested for trait matching. --- src/test/ui/hrtb/hrtb-exists-forall-fn.rs | 23 ++++++++++++ src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 24 ++++++++++++ .../hrtb-exists-forall-trait-contravariant.rs | 35 ++++++++++++++++++ .../hrtb-exists-forall-trait-covariant.rs | 37 +++++++++++++++++++ .../hrtb-exists-forall-trait-invariant.rs | 29 +++++++++++++++ .../hrtb-exists-forall-trait-invariant.stderr | 15 ++++++++ 6 files changed, 163 insertions(+) create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-fn.rs create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-fn.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs new file mode 100644 index 0000000000000..bba1f4dfb86c2 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs @@ -0,0 +1,23 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +trait Trait<T> {} + +fn foo<'a>() -> fn(&'a u32) { + panic!() +} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` + // - This requires (among other things) instantiating `'b` universally, + // yielding `fn(&!b u32)`, in a fresh universe U1 + // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. + + let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr new file mode 100644 index 0000000000000..75ba89f58da1b --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -0,0 +1,24 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/hrtb-exists-forall-fn.rs:22:34 + | +LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer + | ^^^ + | + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'b) })... + = note: ...so that the expression is assignable: + expected for<'b> fn(&'b u32) + found fn(&u32) +note: but, the lifetime must be valid for the call at 22:34... + --> $DIR/hrtb-exists-forall-fn.rs:22:34 + | +LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer + | ^^^^^ +note: ...so type `fn(&u32)` of expression is valid during the expression + --> $DIR/hrtb-exists-forall-fn.rs:22:34 + | +LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs new file mode 100644 index 0000000000000..8801760056ecb --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -0,0 +1,35 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. +// +// compile-pass + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(&'b u32)>, +{ +} + +impl<'a> Trait<fn(&'a u32)> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(&?a u32) <: for<'b> fn(&'b u32)` :- + // - `&'!b u32 <: &?a u32` + // - `!'b: ?a` -- solveable if `?a` is inferred to `'empty` + // - `for<'b> fn(&'b u32) <: fn(&?a u32)` :- + // - `&?a u32 u32 <: &?b u32` + // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'empty`. + + foo::<()>(); +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs new file mode 100644 index 0000000000000..da1bb7cd5fd0b --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -0,0 +1,37 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. +// +// compile-pass + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(fn(&'b u32))>, +{ +} + +impl<'a> Trait<fn(fn(&'a u32))> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>` + // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :- + // - `fn(&!b u32) <: fn(&?a u32)` + // - `&?a u32 <: &!b u32` + // - `?a: !'b` -- solveable if `?a` is inferred to `'static` + // - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :- + // - `fn(&?a u32) <: fn(&?b u32)` + // - `&?b u32 <: &?a u32` + // - `?b: ?a` -- solveable if `?b` is inferred to `'static` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'static`. + + foo::<()>(); +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs new file mode 100644 index 0000000000000..db589548d0e8e --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -0,0 +1,29 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +use std::cell::Cell; + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(Cell<&'b u32>)>, +{ +} + +impl<'a> Trait<fn(Cell<&'a u32>)> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` + // - This requires (among other things) instantiating `'b` universally, + // yielding `fn(&!b u32)`, in a fresh universe U1 + // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. + + foo::<()>(); //~ ERROR cannot infer +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr new file mode 100644 index 0000000000000..7a0986ccdd939 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -0,0 +1,15 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); //~ ERROR cannot infer + | ^^^^^^^^^ + | + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })... + = note: ...so that the types are compatible: + expected Trait<for<'b> fn(std::cell::Cell<&'b u32>)> + found Trait<fn(std::cell::Cell<&u32>)> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. From 1423a6700b0f628e8d9f04ed3605b5ef438a10e9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 30 Oct 2018 16:39:29 -0400 Subject: [PATCH 101/124] tests: move coherence-subtyping from run-pass to compile-fail This is the pattern we no longer accept. --- .../coherence/coherence-subtyping.rs | 4 ++- .../ui/coherence/coherence-subtyping.stderr | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) rename src/test/{run-pass => ui}/coherence/coherence-subtyping.rs (94%) create mode 100644 src/test/ui/coherence/coherence-subtyping.stderr diff --git a/src/test/run-pass/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs similarity index 94% rename from src/test/run-pass/coherence/coherence-subtyping.rs rename to src/test/ui/coherence/coherence-subtyping.rs index b7aa57b5c31f7..2ac9156017829 100644 --- a/src/test/run-pass/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -1,4 +1,3 @@ -// run-pass // Test that two distinct impls which match subtypes of one another // yield coherence errors (or not) depending on the variance. @@ -10,6 +9,7 @@ impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + //~^ ERROR } /////////////////////////////////////////////////////////////////////////// @@ -22,6 +22,7 @@ impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + //~^ ERROR } /////////////////////////////////////////////////////////////////////////// @@ -34,6 +35,7 @@ impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } impl Invariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + //~^ ERROR } fn main() { } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr new file mode 100644 index 0000000000000..92ac829f8000b --- /dev/null +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -0,0 +1,30 @@ +error[E0119]: conflicting implementations of trait `Contravariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: + --> $DIR/coherence-subtyping.rs:21:1 + | +LL | impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { + | -------------------------------------------------------------- first implementation here +... +LL | impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error[E0119]: conflicting implementations of trait `Covariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: + --> $DIR/coherence-subtyping.rs:34:1 + | +LL | impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { + | ---------------------------------------------------------- first implementation here +... +LL | impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error[E0119]: conflicting implementations of trait `Invariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: + --> $DIR/coherence-subtyping.rs:47:1 + | +LL | impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { + | ---------------------------------------------------------- first implementation here +... +LL | impl Invariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0119`. From c1cd91273d383ca6bce2c9f09b645236bd74f209 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 30 Oct 2018 16:57:52 -0400 Subject: [PATCH 102/124] tests: worse diagnostics, but basically same errors --- .../associated-types-eq-hr.rs | 24 +++- .../associated-types-eq-hr.stderr | 110 +++++++----------- .../higher-ranked-projection.bad.stderr | 25 ++-- .../higher-ranked-projection.good.stderr | 3 +- .../higher-ranked-projection.rs | 3 +- .../expect-fn-supply-fn.rs | 9 +- .../expect-fn-supply-fn.stderr | 93 ++++++++------- src/test/ui/generator/auto-trait-regions.rs | 8 +- .../ui/generator/auto-trait-regions.stderr | 65 ++++++----- .../ui/hrtb/hrtb-cache-issue-54302.stderr | 16 ++- src/test/ui/hrtb/hrtb-conflate-regions.rs | 2 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 23 ++-- ...tb-higher-ranker-supertraits-transitive.rs | 2 +- ...igher-ranker-supertraits-transitive.stderr | 21 ++-- .../ui/hrtb/hrtb-higher-ranker-supertraits.rs | 6 +- .../hrtb-higher-ranker-supertraits.stderr | 89 ++++++++------ src/test/ui/hrtb/hrtb-just-for-static.rs | 2 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 22 ++-- src/test/ui/hrtb/hrtb-perfect-forwarding.rs | 2 +- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 31 +++-- src/test/ui/issues/issue-22872.stderr | 19 +-- src/test/ui/issues/issue-40000.rs | 3 +- src/test/ui/issues/issue-40000.stderr | 26 ++++- src/test/ui/issues/issue-54302-cases.rs | 8 +- src/test/ui/issues/issue-54302-cases.stderr | 70 +++++------ src/test/ui/issues/issue-54302.rs | 2 +- src/test/ui/issues/issue-54302.stderr | 16 ++- .../closure-arg-type-mismatch.rs | 6 +- .../closure-arg-type-mismatch.stderr | 73 ++++++++---- .../ui/mismatched_types/closure-mismatch.rs | 3 +- .../mismatched_types/closure-mismatch.stderr | 37 ++---- ...ion-lifetime-bounds-on-fns-where-clause.rs | 2 +- ...lifetime-bounds-on-fns-where-clause.stderr | 17 +-- ...ple-lifetime-bounds-on-fns-where-clause.rs | 2 +- ...lifetime-bounds-on-fns-where-clause.stderr | 17 +-- .../regions/regions-lifetime-bounds-on-fns.rs | 2 +- .../regions-lifetime-bounds-on-fns.stderr | 17 +-- src/test/ui/where-clauses/where-for-self-2.rs | 3 +- .../ui/where-clauses/where-for-self-2.stderr | 21 ++-- 39 files changed, 463 insertions(+), 437 deletions(-) diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index d0245a07e40bd..bc7888f74af22 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -77,23 +77,35 @@ fn tuple_four<T>() // not ok for tuple, two lifetimes, and lifetime matching is invariant } -pub fn main() { +pub fn call_foo() { foo::<IntStruct>(); foo::<UintStruct>(); //~ ERROR type mismatch +} +pub fn call_bar() { bar::<IntStruct>(); //~ ERROR type mismatch bar::<UintStruct>(); +} +pub fn call_tuple_one() { tuple_one::<Tuple>(); - //~^ ERROR E0277 - //~| ERROR type mismatch + //~^ ERROR E0495 + //~| ERROR E0495 +} +pub fn call_tuple_two() { tuple_two::<Tuple>(); - //~^ ERROR E0277 - //~| ERROR type mismatch + //~^ ERROR E0495 + //~| ERROR E0495 +} +pub fn call_tuple_three() { tuple_three::<Tuple>(); +} +pub fn call_tuple_four() { tuple_four::<Tuple>(); - //~^ ERROR E0277 + //~^ ERROR E0495 } + +fn main() { } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 5e04dc5f8c5d9..226733da0f63f 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -17,7 +17,7 @@ LL | | } | |_^ error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize` - --> $DIR/associated-types-eq-hr.rs:84:5 + --> $DIR/associated-types-eq-hr.rs:86:5 | LL | bar::<IntStruct>(); //~ ERROR type mismatch | ^^^^^^^^^^^^^^^^ expected isize, found usize @@ -34,93 +34,67 @@ LL | | // ok for UintStruct, but not IntStruct LL | | } | |_^ -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:87:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/associated-types-eq-hr.rs:91:5 | LL | tuple_one::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 + | ^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_one<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:20), 'x) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:21), 'y) })... + = note: ...so that the types are compatible: + expected TheTrait<(&'x isize, &'y isize)> + found TheTrait<(&isize, &isize)> -error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:87:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/associated-types-eq-hr.rs:91:5 | LL | tuple_one::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 + | ^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_one<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:20), 'x) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:21), 'y) })... + = note: ...so that the types are compatible: + expected TheTrait<(&'x isize, &'y isize)> + found TheTrait<(&isize, &isize)> -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:91:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/associated-types-eq-hr.rs:97:5 | LL | tuple_two::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 + | ^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_two<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:23), 'x) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:24), 'y) })... + = note: ...so that the types are compatible: + expected TheTrait<(&'x isize, &'y isize)> + found TheTrait<(&isize, &isize)> -error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:91:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/associated-types-eq-hr.rs:97:5 | LL | tuple_two::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | ^^^^^^^^^^^^^^^^^^ | -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 - | -LL | / fn tuple_two<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:23), 'x) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:24), 'y) })... + = note: ...so that the types are compatible: + expected TheTrait<(&'x isize, &'y isize)> + found TheTrait<(&isize, &isize)> -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/associated-types-eq-hr.rs:107:5 | LL | tuple_four::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_four` - --> $DIR/associated-types-eq-hr.rs:74:1 + | ^^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_four<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> -LL | | { -LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:28), 'x) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:29), 'y) })... + = note: ...so that the types are compatible: + expected TheTrait<(&'x isize, &'y isize)> + found TheTrait<(&isize, &isize)> error: aborting due to 7 previous errors -Some errors occurred: E0271, E0277. +Some errors occurred: E0271, E0495. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index cc69e849fe144..b5355e6009975 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,17 +1,24 @@ -error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ | -note: required by `foo` - --> $DIR/higher-ranked-projection.rs:14:1 + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'a) })... + = note: ...so that the types are compatible: + expected Mirror + found Mirror +note: but, the lifetime must be valid for the expression at 25:5... + --> $DIR/higher-ranked-projection.rs:25:5 | -LL | / fn foo<U, T>(_t: T) -LL | | where for<'a> &'a T: Mirror<Image=U> -LL | | {} - | |__^ +LL | foo(()); + | ^^^ +note: ...so type `fn(()) {foo::<&(), ()>}` of expression is valid during the expression + --> $DIR/higher-ranked-projection.rs:25:5 + | +LL | foo(()); + | ^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index 632fe493e1f3f..a837df0cd2429 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,8 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` -LL | | //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime +LL | | //[bad]~^ ERROR E0495 LL | | } | |_^ diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index be6300c418293..2d2221c6c6392 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,6 +23,5 @@ fn foo<U, T>(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` - //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime + //[bad]~^ ERROR E0495 } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 8c7d3cbad33c4..49f6565540b7e 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -28,14 +28,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR type mismatch in closure arguments + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR type mismatch in closure arguments + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_closure() { @@ -43,8 +43,9 @@ fn expect_bound_supply_free_from_closure() { // bound at the closure level, but we expect something bound at // the argument level. type Foo<'a> = fn(&'a u32); - with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {}); - //~^ ERROR type mismatch in closure arguments + with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + //~^ ERROR cannot infer + }); } fn expect_bound_supply_bound<'x>(x: &'x u32) { diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 9c85743106776..d140e9989a3f6 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -36,58 +36,61 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:30:52 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^^^^^^^^ lifetime mismatch + | + = note: expected type `fn(&u32)` + found type `for<'r> fn(&'r u32)` + = note: lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) })... +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 30:48 + --> $DIR/expect-fn-supply-fn.rs:30:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `for<'a, 'r> fn(fn(&'a u32), &'r i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 - | -LL | / fn with_closure_expecting_fn_with_free_region<F>(_: F) -LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) -LL | | { -LL | | } - | |_^ + | ^^^^^^^^^^^^^^^^^^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:37:53 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ + | ^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `for<'r> fn(&'r u32)` + found type `fn(&'x u32)` + = note: lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 34:37 + --> $DIR/expect-fn-supply-fn.rs:34:37 + | +LL | fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { + | ^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 - | -LL | with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _` - | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements + --> $DIR/expect-fn-supply-fn.rs:46:53 + | +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^^^^^^^ + | + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... + = note: ...so that the types are compatible: + expected for<'r> fn(&'r u32) + found fn(&u32) +note: but, the lifetime must be valid for the expression at 46:65... + --> $DIR/expect-fn-supply-fn.rs:46:65 + | +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | _________________________________________________________________^ +LL | | //~^ ERROR cannot infer +LL | | }); + | |_____^ +note: ...so that the type `fn(&u32)` will meet its required lifetime bounds + --> $DIR/expect-fn-supply-fn.rs:46:53 + | +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^^^^^^^ error: aborting due to 5 previous errors -Some errors occurred: E0308, E0631. +Some errors occurred: E0308, E0495. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index 2110e8a5407ba..4523e05696a2b 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -27,7 +27,9 @@ fn main() { yield; assert_foo(x); }; - assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied + assert_foo(gen); + //~^ ERROR mismatched types + //~| ERROR mismatched types // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); @@ -44,5 +46,7 @@ fn main() { yield; assert_foo(a); }; - assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied + assert_foo(gen); + //~^ ERROR E0495 + //~| ERROR E0495 } diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index a301dc2ff9a00..3998ffe2522b4 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,37 +1,50 @@ -error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` +error[E0308]: mismatched types --> $DIR/auto-trait-regions.rs:30:5 | -LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied - | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No` +LL | assert_foo(gen); + | ^^^^^^^^^^ lifetime mismatch | - = help: the following implementations were found: - <No as Foo> - = note: required because it appears within the type `OnlyFooIfStaticRef` - = note: required because it appears within the type `&OnlyFooIfStaticRef` - = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}` - = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` -note: required by `assert_foo` - --> $DIR/auto-trait-regions.rs:20:1 + = note: expected type `Foo` + found type `Foo` + = note: lifetime RePlaceholder(Placeholder { universe: U31, name: BrAnon(1) })... + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/auto-trait-regions.rs:30:5 + | +LL | assert_foo(gen); + | ^^^^^^^^^^ lifetime mismatch | -LL | fn assert_foo<T: Foo>(f: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `Foo` + found type `Foo` + = note: lifetime RePlaceholder(Placeholder { universe: U35, name: BrAnon(1) })... + = note: ...does not necessarily outlive the static lifetime -error[E0279]: the requirement `for<'r, 's> 'r : 's` is not satisfied (`expected bound lifetime parameter, found concrete lifetime`) - --> $DIR/auto-trait-regions.rs:47:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + --> $DIR/auto-trait-regions.rs:49:5 | -LL | assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied +LL | assert_foo(gen); | ^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'r, 's> Foo` for `A<'_, '_>` - = note: required because it appears within the type `for<'r, 's> {A<'r, 's>, ()}` - = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:42:15: 46:6 for<'r, 's> {A<'r, 's>, ()}]` -note: required by `assert_foo` - --> $DIR/auto-trait-regions.rs:20:1 + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U47, name: BrAnon(2) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U47, name: BrAnon(1) })... + = note: ...so that the types are compatible: + expected Foo + found Foo + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + --> $DIR/auto-trait-regions.rs:49:5 + | +LL | assert_foo(gen); + | ^^^^^^^^^^ | -LL | fn assert_foo<T: Foo>(f: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U51, name: BrAnon(2) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U51, name: BrAnon(1) })... + = note: ...so that the types are compatible: + expected Foo + found Foo -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0277, E0279. -For more information about an error, try `rustc --explain E0277`. +Some errors occurred: E0308, E0495. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index 061d0e309c500..940a6e3f06853 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -1,17 +1,15 @@ -error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`) +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements --> $DIR/hrtb-cache-issue-54302.rs:19:5 | LL | assert_deserialize_owned::<&'static str>(); //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str` - = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str` -note: required by `main::assert_deserialize_owned` - --> $DIR/hrtb-cache-issue-54302.rs:18:5 - | -LL | fn assert_deserialize_owned<T: DeserializeOwned>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'de) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Deserialize<'de> + found Deserialize<'_> error: aborting due to previous error -For more information about this error, try `rustc --explain E0279`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs index 8953a847213d5..391303676d784 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.rs +++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs @@ -25,6 +25,6 @@ impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct } fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region -fn b() { want_foo2::<SomeStruct>(); } //~ ERROR E0277 +fn b() { want_foo2::<SomeStruct>(); } //~ ERROR fn main() { } diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index e2a99ea8472ba..24d374e470e32 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,20 +1,15 @@ -error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/hrtb-conflate-regions.rs:28:10 | -LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` +LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the following implementations were found: - <SomeStruct as Foo<(&'a isize, &'a isize)>> -note: required by `want_foo2` - --> $DIR/hrtb-conflate-regions.rs:8:1 - | -LL | / fn want_foo2<T>() -LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> -LL | | { -LL | | } - | |_^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'a) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:12), 'b) })... + = note: ...so that the types are compatible: + expected Foo<(&'a isize, &'b isize)> + found Foo<(&isize, &isize)> error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs index 99001d7053c62..f9ae1429ee4a2 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs @@ -44,7 +44,7 @@ fn want_qux<B>(b: &B) where B : Qux { want_foo_for_any_tcx(b); - want_bar_for_any_ccx(b); //~ ERROR E0277 + want_bar_for_any_ccx(b); //~ ERROR } fn main() {} diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index d233ed475241a..b02764184fbe9 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,19 +1,14 @@ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | -LL | want_bar_for_any_ccx(b); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` +LL | want_bar_for_any_ccx(b); //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 - | -LL | / fn want_bar_for_any_ccx<B>(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | } - | |_^ + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'static>` + = note: lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:16), 'ccx) })... + = note: ...does not necessarily outlive the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs index f430a10d2a722..638587f428d78 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs @@ -15,7 +15,8 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) where F : Foo<'x> { want_foo_for_some_tcx(f); - want_foo_for_any_tcx(f); //~ ERROR E0277 + want_foo_for_any_tcx(f); //~ ERROR E0308 + //~^ ERROR E0308 } fn want_foo_for_any_tcx<F>(f: &F) @@ -32,7 +33,8 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_foo_for_any_tcx(b); want_bar_for_some_ccx(b); - want_bar_for_any_ccx(b); //~ ERROR E0277 + want_bar_for_any_ccx(b); //~ ERROR E0308 + //~^ ERROR E0308 } fn want_bar_for_any_ccx<B>(b: &B) diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index fe485c5b259eb..71ed59ce2ff7e 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,40 +1,63 @@ -error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | -LL | want_foo_for_any_tcx(f); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` +LL | want_foo_for_any_tcx(f); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound -note: required by `want_foo_for_any_tcx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + = note: expected type `for<'tcx> Foo<'tcx>` + found type `Foo<'x>` + = note: lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:15), 'tcx) })... +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 14:26 + --> $DIR/hrtb-higher-ranker-supertraits.rs:14:26 | -LL | / fn want_foo_for_any_tcx<F>(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> -LL | | { -LL | | want_foo_for_some_tcx(f); -LL | | want_foo_for_any_tcx(f); -LL | | } - | |_^ +LL | fn want_foo_for_some_tcx<'x,F>(f: &'x F) + | ^^ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 - | -LL | want_bar_for_any_ccx(b); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 - | -LL | / fn want_bar_for_any_ccx<B>(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | want_foo_for_some_tcx(b); -... | -LL | | want_bar_for_any_ccx(b); -LL | | } - | |_^ +error[E0308]: mismatched types + --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 + | +LL | want_foo_for_any_tcx(f); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `for<'tcx> Foo<'tcx>` + found type `Foo<'x>` +note: the lifetime 'x as defined on the function body at 14:26... + --> $DIR/hrtb-higher-ranker-supertraits.rs:14:26 + | +LL | fn want_foo_for_some_tcx<'x,F>(f: &'x F) + | ^^ + = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:15), 'tcx) }) + +error[E0308]: mismatched types + --> $DIR/hrtb-higher-ranker-supertraits.rs:36:5 + | +LL | want_bar_for_any_ccx(b); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'x>` + = note: lifetime RePlaceholder(Placeholder { universe: U8, name: BrNamed(crate0:DefIndex(1:19), 'ccx) })... +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 29:26 + --> $DIR/hrtb-higher-ranker-supertraits.rs:29:26 + | +LL | fn want_bar_for_some_ccx<'x,B>(b: &B) + | ^^ + +error[E0308]: mismatched types + --> $DIR/hrtb-higher-ranker-supertraits.rs:36:5 + | +LL | want_bar_for_any_ccx(b); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'x>` +note: the lifetime 'x as defined on the function body at 29:26... + --> $DIR/hrtb-higher-ranker-supertraits.rs:29:26 + | +LL | fn want_bar_for_some_ccx<'x,B>(b: &B) + | ^^ + = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U8, name: BrNamed(crate0:DefIndex(1:19), 'ccx) }) -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs index c162c777c0bad..3aee241ccd2d7 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.rs +++ b/src/test/ui/hrtb/hrtb-just-for-static.rs @@ -21,7 +21,7 @@ fn give_any() { struct StaticInt; impl Foo<&'static isize> for StaticInt { } fn give_static() { - want_hrtb::<StaticInt>() //~ ERROR `for<'a> StaticInt: Foo<&'a isize>` is not satisfied + want_hrtb::<StaticInt>() //~ ERROR } fn main() { } diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 38865fac86ded..d3c2f7d059a6f 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,20 +1,14 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | want_hrtb::<StaticInt>() //~ ERROR `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::<StaticInt>() //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = help: the following implementations were found: - <StaticInt as Foo<&'static isize>> -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 - | -LL | / fn want_hrtb<T>() -LL | | where T : for<'a> Foo<&'a isize> -LL | | { -LL | | } - | |_^ + = note: expected type `Foo<&'a isize>` + found type `Foo<&'static isize>` + = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'a) })... + = note: ...does not necessarily outlive the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 90e1773a3f62d..31dad39efc3f5 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs @@ -43,7 +43,7 @@ fn foo_hrtb_bar_not<'b,T>(mut t: T) // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // clause only specifies `T : Bar<&'b isize>`. - foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied + foo_hrtb_bar_not(&mut t); //~ ERROR E0495 } fn foo_hrtb_bar_hrtb<T>(mut t: T) diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 6cada7ac78f4b..2de60a79a85bd 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -1,23 +1,22 @@ -error[E0277]: the trait bound `for<'a> T: Bar<&'a isize>` is not satisfied +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/hrtb-perfect-forwarding.rs:46:5 | -LL | foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied - | ^^^^^^^^^^^^^^^^ the trait `for<'a> Bar<&'a isize>` is not implemented for `T` +LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0495 + | ^^^^^^^^^^^^^^^^ | - = help: consider adding a `where for<'a> T: Bar<&'a isize>` bound - = note: required because of the requirements on the impl of `for<'a> Foo<&'a isize>` for `&mut T` -note: required by `foo_hrtb_bar_not` - --> $DIR/hrtb-perfect-forwarding.rs:39:1 + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:23), 'a) })... + = note: ...so that the types are compatible: + expected Foo<&'a isize> + found Foo<&isize> +note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 39:21... + --> $DIR/hrtb-perfect-forwarding.rs:39:21 | -LL | / fn foo_hrtb_bar_not<'b,T>(mut t: T) -LL | | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> -LL | | { -LL | | // Not OK -- The forwarding impl for `Foo` requires that `Bar` also -... | -LL | | foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied -LL | | } - | |_^ +LL | fn foo_hrtb_bar_not<'b,T>(mut t: T) + | ^^ + = note: ...so that the types are compatible: + expected Bar<&isize> + found Bar<&'b isize> error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index 231080add9bd0..ebd096f1dde5a 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -1,23 +1,14 @@ -error[E0277]: the trait bound `for<'b> P: Process<'b>` is not satisfied +error[E0277]: `<P as Process<'_>>::Item` is not an iterator --> $DIR/issue-22872.rs:20:36 | LL | let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> Process<'b>` is not implemented for `P` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator | - = help: consider adding a `where for<'b> P: Process<'b>` bound + = help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item` + = help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` -error[E0277]: `<P as Process<'b>>::Item` is not an iterator - --> $DIR/issue-22872.rs:20:36 - | -LL | let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'b>>::Item` is not an iterator - | - = help: the trait `for<'b> std::iter::Iterator` is not implemented for `<P as Process<'b>>::Item` - = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` - = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-40000.rs b/src/test/ui/issues/issue-40000.rs index 2d1e1d07a26ff..c7d1900ada958 100644 --- a/src/test/ui/issues/issue-40000.rs +++ b/src/test/ui/issues/issue-40000.rs @@ -3,6 +3,5 @@ fn main() { fn foo(x: Box<Fn(&i32)>) {} let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; - foo(bar); //~ ERROR mismatched types - //~| expected concrete lifetime, found bound lifetime parameter + foo(bar); //~ ERROR E0495 } diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 3ff5870348109..3aa1da8680c02 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -1,12 +1,26 @@ -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/issue-40000.rs:6:9 | -LL | foo(bar); //~ ERROR mismatched types - | ^^^ expected concrete lifetime, found bound lifetime parameter +LL | foo(bar); //~ ERROR E0495 + | ^^^ | - = note: expected type `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` - found type `std::boxed::Box<dyn std::ops::Fn(_)>` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U8, name: BrAnon(0) })... + = note: ...so that the types are compatible: + expected dyn for<'r> std::ops::Fn(&'r i32) + found dyn std::ops::Fn(&i32) +note: but, the lifetime must be valid for the block suffix following statement 2 at 5:5... + --> $DIR/issue-40000.rs:5:5 + | +LL | / let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; +LL | | foo(bar); //~ ERROR E0495 +LL | | } + | |_^ +note: ...so that variable is valid at time of its declaration + --> $DIR/issue-40000.rs:5:9 + | +LL | let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; + | ^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-54302-cases.rs b/src/test/ui/issues/issue-54302-cases.rs index 0c852a2eb6321..286d37b182e31 100644 --- a/src/test/ui/issues/issue-54302-cases.rs +++ b/src/test/ui/issues/issue-54302-cases.rs @@ -61,25 +61,25 @@ impl<T> RefFoo<T> for T where for<'a> &'a T: Foo<'static, T> { fn coerce_lifetime1(a: &u32) -> &'static u32 { <u32 as RefFoo<u32>>::ref_foo(a) - //~^ ERROR the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied + //~^ ERROR cannot infer } fn coerce_lifetime2(a: &i32) -> &'static i32 { <i32 as RefFoo<i32>>::ref_foo(a) - //~^ ERROR the requirement `for<'a> 'a : ` is not satisfied + //~^ ERROR cannot infer } fn coerce_lifetime3(a: &u64) -> &'static u64 { <u64 as RefFoo<u64>>::ref_foo(a) - //~^ ERROR type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` + //~^ ERROR cannot infer } fn coerce_lifetime4(a: &i64) -> &'static i64 { <i64 as RefFoo<i64>>::ref_foo(a) - //~^ ERROR type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` + //~^ ERROR cannot infer } fn main() {} diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 0ed88463277d5..09a4e091d2bcf 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -1,65 +1,51 @@ -error[E0277]: the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements --> $DIR/issue-54302-cases.rs:63:5 | LL | <u32 as RefFoo<u32>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo2<'_, u32>` is not implemented for `&'a u32` - | - = help: the following implementations were found: - <&'x u32 as Foo2<'x, u32>> - = note: required because of the requirements on the impl of `for<'a> Foo<'static, u32>` for `&'a u32` - = note: required because of the requirements on the impl of `RefFoo<u32>` for `u32` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Foo<'static, u32> + found Foo<'_, u32> -error[E0279]: the requirement `for<'a> 'a : ` is not satisfied (`expected bound lifetime parameter 'a, found concrete lifetime`) +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements --> $DIR/issue-54302-cases.rs:69:5 | LL | <i32 as RefFoo<i32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i32>` for `&'a i32` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, i32>` for `&'a i32` - = note: required because of the requirements on the impl of `RefFoo<i32>` for `i32` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 - | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Foo<'static, i32> + found Foo<'_, i32> -error[E0271]: type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements --> $DIR/issue-54302-cases.rs:75:5 | LL | <u64 as RefFoo<u64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime - | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, u64>` for `&'a u64` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, u64>` for `&'a u64` - = note: required because of the requirements on the impl of `RefFoo<u64>` for `u64` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Foo<'static, u64> + found Foo<'_, u64> -error[E0271]: type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements --> $DIR/issue-54302-cases.rs:81:5 | LL | <i64 as RefFoo<i64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime - | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i64>` for `&'a i64` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, i64>` for `&'a i64` - = note: required because of the requirements on the impl of `RefFoo<i64>` for `i64` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Foo<'static, i64> + found Foo<'_, i64> error: aborting due to 4 previous errors -Some errors occurred: E0271, E0277, E0279. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-54302.rs b/src/test/ui/issues/issue-54302.rs index c681d37cdae00..35cdc73a78fd0 100644 --- a/src/test/ui/issues/issue-54302.rs +++ b/src/test/ui/issues/issue-54302.rs @@ -11,7 +11,7 @@ fn main() { // Then why does it implement DeserializeOwned? This compiles. fn assert_deserialize_owned<T: DeserializeOwned>() {} assert_deserialize_owned::<&'static str>(); - //~^ ERROR the requirement `for<'de> 'de : ` is not satisfied + //~^ ERROR E0495 // It correctly does not implement for<'de> Deserialize<'de>. //fn assert_hrtb<T: for<'de> Deserialize<'de>>() {} diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index 2d95aa2b156f2..b456d2582ffd6 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -1,17 +1,15 @@ -error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`) +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements --> $DIR/issue-54302.rs:13:5 | LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str` - = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str` -note: required by `main::assert_deserialize_owned` - --> $DIR/issue-54302.rs:12:5 - | -LL | fn assert_deserialize_owned<T: DeserializeOwned>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'de) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the types are compatible: + expected Deserialize<'de> + found Deserialize<'_> error: aborting due to previous error -For more information about this error, try `rustc --explain E0279`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index c5d9e4b9b766b..f71a1736d4d3f 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,8 @@ fn main() { fn baz<F: Fn(*mut &u32)>(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(f); //~ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 5dd6887005e83..2cd63099bb756 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,34 +22,67 @@ LL | a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR type mismatch - | ^^^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` +LL | baz(f); //~ ERROR mismatched types + | ^^^ lifetime mismatch | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + = note: lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) })... +note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 9:10 + --> $DIR/closure-arg-type-mismatch.rs:9:10 | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ -error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR type mismatch - | ^^^ expected bound lifetime parameter, found concrete lifetime +LL | baz(f); //~ ERROR mismatched types + | ^^^ lifetime mismatch | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` + = note: lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... +note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 9:10 + --> $DIR/closure-arg-type-mismatch.rs:9:10 | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); //~ ERROR mismatched types + | ^^^ lifetime mismatch + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` +note: the lifetime 'a as defined on the function body at 9:10... + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ + = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) }) + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); //~ ERROR mismatched types + | ^^^ lifetime mismatch + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` +note: the lifetime 'a as defined on the function body at 9:10... + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ + = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) }) + +error: aborting due to 7 previous errors -Some errors occurred: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors occurred: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe7196..0f28e5dfd7ee0 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,6 +5,5 @@ impl<T: Fn(&())> Foo for T {} fn baz<T: Foo>(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(|_| ()); //~ ERROR E0495 } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index e55047e96c297..f028817a935a7 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,32 +1,15 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/closure-mismatch.rs:8:5 | -LL | baz(|_| ()); //~ ERROR type mismatch - | ^^^ expected bound lifetime parameter, found concrete lifetime +LL | baz(|_| ()); //~ ERROR E0495 + | ^^^ | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz<T: Foo>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | baz(|_| ()); //~ ERROR type mismatch - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz<T: Foo>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U6, name: BrAnon(0) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U6, name: BrAnon(0) })... + = note: ...so that the types are compatible: + expected for<'r> std::ops::Fn<(&'r (),)> + found std::ops::Fn<(&(),)> -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs index ab4c6d9cf9198..e5514d32c4e9f 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -17,7 +17,7 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types + let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 } fn e() { diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 5c8b3d3ba6922..3824755fa06f5 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -16,16 +16,19 @@ LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | a(x, y); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | -LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter +LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 + | ^ | - = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...so that the expression is assignable: + expected for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize) + found for<'r, 's> fn(&'r mut &isize, &'s mut &isize) error: aborting due to 3 previous errors -Some errors occurred: E0308, E0623. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0495, E0623. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 8e7f4ccad9cb4..3e635300d7b68 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -19,7 +19,7 @@ fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR mismatched types + let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0495 } fn e() { diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 01899349bf701..f694d31264070 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -27,16 +27,19 @@ LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | a(x, y, z); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | -LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0495 + | ^ | - = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...so that the expression is assignable: + expected for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize) + found for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) error: aborting due to 4 previous errors -Some errors occurred: E0308, E0623. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0495, E0623. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs index 2f35883cc9916..6ebfc3f80d252 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -17,7 +17,7 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types + let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 } fn e() { diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index c4d4a159a9c32..20e28e8877fca 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -16,16 +16,19 @@ LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | a(x, y); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | -LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter +LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 + | ^ | - = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... + = note: ...so that the expression is assignable: + expected for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize) + found for<'r, 's> fn(&'r mut &isize, &'s mut &isize) error: aborting due to 3 previous errors -Some errors occurred: E0308, E0623. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0495, E0623. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 10b25c734037a..c69055fe0cc82 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,6 +18,5 @@ fn foo<T>(x: &T) {} fn main() { - foo(&X); - //~^ error: `for<'a> &'a _: Bar` is not satisfied + foo(&X); //~ ERROR E0308 } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index dbe68b82c24cb..04d7bbabb2a57 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,19 +1,14 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied +error[E0308]: mismatched types --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); //~ ERROR E0308 + | ^^^ lifetime mismatch | - = help: the following implementations were found: - <&'static u32 as Bar> -note: required by `foo` - --> $DIR/where-for-self-2.rs:16:1 - | -LL | / fn foo<T>(x: &T) -LL | | where for<'a> &'a T: Bar -LL | | {} - | |__^ + = note: expected type `Bar` + found type `Bar` + = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:10), 'a) })... + = note: ...does not necessarily outlive the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. From a0ccf9920d88f298956443bf787dc0d9190dd540 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 31 Dec 2018 13:45:40 -0500 Subject: [PATCH 103/124] tests: cases where we now do the right thing but did not before Fixes #33684 --- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 13 ++++---- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 22 +++++++------- .../hr-subtype.bound_a_vs_bound_a.stderr | 6 ++-- .../hr-subtype.bound_a_vs_bound_b.stderr | 6 ++-- .../hr-subtype.bound_a_vs_free_x.stderr | 12 +++++++- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 22 +++++++------- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 22 +++++++------- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 6 ++-- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 22 +++++++------- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 13 ++++---- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 6 ++-- .../hr-subtype.free_x_vs_free_x.stderr | 6 ++-- src/test/ui/hr-subtype/hr-subtype.rs | 20 ++++++------- src/test/ui/lub-glb/old-lub-glb-hr.rs | 9 ++++-- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 17 ----------- ...regions-fn-subtyping-return-static-fail.rs | 9 ++---- ...ons-fn-subtyping-return-static-fail.stderr | 28 +++++++---------- .../regions-fn-subtyping-return-static.rs | 5 ++-- .../regions-fn-subtyping-return-static.stderr | 30 ++++++++++++++----- 19 files changed, 137 insertions(+), 137 deletions(-) delete mode 100644 src/test/ui/lub-glb/old-lub-glb-hr.stderr diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index 8e2b0b8c60045..4069e3b25ade0 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,16 +1,19 @@ -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } | |_________________________________________________________________________________________- in this macro invocation | - = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>` - found type `std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:26), 'b) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:25), 'a) })... + = note: ...so that the expression is assignable: + expected std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32> + found std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32> error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index dbb5018139076..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), -LL | | for<'a> fn(&'a u32, &'a u32)) } - | |__________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>` - found type `std::option::Option<for<'a> fn(&'a u32, &'a u32)>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index db9892b48a6f7..1225842665d99 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ lifetime mismatch ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } @@ -10,6 +10,16 @@ LL | | fn(&'x u32)) } | = note: expected type `std::option::Option<for<'a> fn(&'a u32)>` found type `std::option::Option<fn(&'x u32)>` + = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:23), 'a) })... +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 48:22 + --> $DIR/hr-subtype.rs:48:22 + | +LL | fn supertype<'x,'y:'x,'z:'y>() { + | ^^ +... +LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +LL | | fn(&'x u32)) } + | |___________________________________________- in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index e9fb73411bd39..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), -LL | | for<'a> fn(Co<'a>, Co<'a>)) } - | |______________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>` - found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index d0e80faa68e8b..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, -LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } - | |______________________________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index 3605ecf4f8667..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, -LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } - | |______________________________________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found type `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index fae6e9b5c89ca..1a806bd2cb550 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,16 +1,19 @@ -error[E0308]: mismatched types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | |__________________________________________________________________________- in this macro invocation | - = note: expected type `std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>` - found type `std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)>` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:25), 'a) })... + = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:26), 'b) })... + = note: ...so that the expression is assignable: + expected std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)> + found std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)> error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index 4157953fb9068..ad4f39f840528 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -31,21 +31,17 @@ macro_rules! check { #[cfg($rev)] fn subtype<'x,'y:'x,'z:'y>() { gimme::<$t2>(None::<$t1>); - //[free_inv_x_vs_free_inv_y]~^ ERROR mismatched types + //[free_inv_x_vs_free_inv_y]~^ ERROR } #[cfg($rev)] fn supertype<'x,'y:'x,'z:'y>() { gimme::<$t1>(None::<$t2>); - //[bound_a_vs_free_x]~^ ERROR mismatched types - //[free_x_vs_free_y]~^^ ERROR mismatched types - //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR mismatched types - //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR mismatched types - //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR mismatched types - //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types - //[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR mismatched types - //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR mismatched types - //[bound_co_a_co_b_ret_contra_a]~^^^^^^^^^ ERROR mismatched types + //[bound_a_vs_free_x]~^ ERROR + //[free_x_vs_free_y]~^^ ERROR + //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR + //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR + //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR } } } @@ -103,4 +99,8 @@ fn main() { //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +//[bound_a_b_vs_bound_a]~^^^^^^ ERROR compilation successful +//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR compilation successful +//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^ ERROR compilation successful +//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful } diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index 049905467769e..324dc86bd92b8 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -1,11 +1,16 @@ // Test that we give a note when the old LUB/GLB algorithm would have -// succeeded but the new code (which is stricter) gives an error. +// succeeded but the new code (which requires equality) gives an +// error. However, now that we handle subtyping correctly, we no +// longer get an error, because we recognize these two types as +// equivalent! +// +// compile-pass fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { - let z = match 22 { //~ ERROR incompatible types + let z = match 22 { 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr deleted file mode 100644 index 9c397a8fd2cc5..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: match arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:8:13 - | -LL | let z = match 22 { //~ ERROR incompatible types - | _____________^ -LL | | 0 => x, -LL | | _ => y, - | | - match arm with an incompatible type -LL | | }; - | |_____^ expected bound lifetime parameter, found concrete lifetime - | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found type `for<'a> fn(&'a u8, &'a u8)` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index a8fe562656ebb..242119cc201da 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -37,8 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly - want_F(bar); //~ ERROR E0308 + want_F(bar); want_F(baz); } @@ -46,11 +45,7 @@ fn supply_F() { fn supply_G() { want_G(foo); want_G(bar); - want_G(baz); - //~^ ERROR mismatched types - //~| expected type `for<'cx> fn(&'cx S) -> &'static S` - //~| found type `for<'r> fn(&'r S) -> &'r S {baz}` - //~| expected concrete lifetime, found bound lifetime parameter 'cx + want_G(baz); //~ ERROR } pub fn main() { diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 0bf6e0514d21e..c9ccb9b6ded3d 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,21 +1,15 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:41:12 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | -LL | want_F(bar); //~ ERROR E0308 - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx +LL | want_G(baz); //~ ERROR + | ^^^ | - = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` - found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'cx) })... + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the expression is assignable: + expected for<'cx> fn(&'cx S) -> &'static S + found for<'r> fn(&'r S) -> &'r S -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:49:12 - | -LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected type `for<'cx> fn(&'cx S) -> &'static S` - found type `for<'r> fn(&'r S) -> &'r S {baz}` - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa5f6a334b0f0..4d6d342f571a5 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// compile-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -37,8 +39,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly - want_F(bar); //~ ERROR E0308 + want_F(bar); want_F(baz); } diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr index 30646fe79659e..61eaf9fcf109b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr @@ -1,12 +1,26 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 +warning: function `want_F` should have a snake case name such as `want_f` + --> $DIR/regions-fn-subtyping-return-static.rs:18:1 | -LL | want_F(bar); //~ ERROR E0308 - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx +LL | fn want_F(f: F) { } + | ^^^^^^^^^^^^^^^^^^^ | - = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` - found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + = note: #[warn(non_snake_case)] on by default -error: aborting due to previous error +warning: function `want_G` should have a snake case name such as `want_g` + --> $DIR/regions-fn-subtyping-return-static.rs:22:1 + | +LL | fn want_G(f: G) { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: function `supply_F` should have a snake case name such as `supply_f` + --> $DIR/regions-fn-subtyping-return-static.rs:39:1 + | +LL | / fn supply_F() { +LL | | want_F(foo); +LL | | +LL | | want_F(bar); +LL | | +LL | | want_F(baz); +LL | | } + | |_^ -For more information about this error, try `rustc --explain E0308`. From 581dc66062d75257ea73a1e340dd92476991c71a Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 31 Dec 2018 13:45:48 -0500 Subject: [PATCH 104/124] WIP other test changes --- src/test/ui/coherence/coherence-subtyping.stderr | 6 +++--- src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr | 4 ++-- src/test/ui/issues/issue-22872.rs | 1 - src/test/ui/lub-glb/old-lub-glb-object.stderr | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index 92ac829f8000b..eb68768eed072 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Contravariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:21:1 + --> $DIR/coherence-subtyping.rs:11:1 | LL | impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { | -------------------------------------------------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` error[E0119]: conflicting implementations of trait `Covariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:34:1 + --> $DIR/coherence-subtyping.rs:24:1 | LL | impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { | ---------------------------------------------------------- first implementation here @@ -17,7 +17,7 @@ LL | impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` error[E0119]: conflicting implementations of trait `Invariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:47:1 + --> $DIR/coherence-subtyping.rs:37:1 | LL | impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { | ---------------------------------------------------------- first implementation here diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index 1225842665d99..bb1a828f3da4b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -11,8 +11,8 @@ LL | | fn(&'x u32)) } = note: expected type `std::option::Option<for<'a> fn(&'a u32)>` found type `std::option::Option<fn(&'x u32)>` = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:23), 'a) })... -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 48:22 - --> $DIR/hr-subtype.rs:48:22 +note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 38:22 + --> $DIR/hr-subtype.rs:38:22 | LL | fn supertype<'x,'y:'x,'z:'y>() { | ^^ diff --git a/src/test/ui/issues/issue-22872.rs b/src/test/ui/issues/issue-22872.rs index a6130d21b5d39..8ef4af15bd462 100644 --- a/src/test/ui/issues/issue-22872.rs +++ b/src/test/ui/issues/issue-22872.rs @@ -19,7 +19,6 @@ pub trait Process<'a> { fn push_process<P>(process: P) where P: Process<'static> { let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); //~^ ERROR is not an iterator -//~| ERROR is not satisfied } fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 3a7478b73b85a..2ed180f25dc02 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,4 +1,4 @@ -error[E0308]: match arms have incompatible types +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements --> $DIR/old-lub-glb-object.rs:10:13 | LL | let z = match 22 { //~ ERROR cannot infer From 616898f034571565e0d4617704740d44d4cf8a4a Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Wed, 31 Oct 2018 13:20:48 -0400 Subject: [PATCH 105/124] remove outdated `rustc_driver` tests they are subsumed by `hr-subtype/hr-subtype.rs` and other tests --- src/librustc_driver/test.rs | 51 ------------------------------------- 1 file changed, 51 deletions(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index a5f7d676862e0..9c027f110eb4e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -7,7 +7,6 @@ use errors::{DiagnosticBuilder, Level}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::type_variable::TypeVariableOrigin; use rustc::infer::{self, InferOk, InferResult, SuppressRegionErrors}; use rustc::middle::region; use rustc::session::config::{OutputFilenames, OutputTypes}; @@ -26,7 +25,6 @@ use syntax::ast; use syntax::feature_gate::UnstableFeatures; use syntax::source_map::{FileName, FilePathMapping, SourceMap}; use syntax::symbol::Symbol; -use syntax_pos::DUMMY_SP; use std::path::PathBuf; use std::sync::mpsc; @@ -431,17 +429,6 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } } } - - /// Checks that `t1 <: t2` is false (this may register additional - /// region checks). - pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub(t1, t2) { - Err(_) => {} - Ok(_) => { - panic!("unexpected success computing sub({:?},{:?})", t1, t2); - } - } - } } #[test] @@ -470,25 +457,6 @@ fn contravariant_region_ptr_err() { }) } -#[test] -fn sub_free_bound_false() { - //! Test that: - //! - //! fn(&'a isize) <: for<'b> fn(&'b isize) - //! - //! *does not* hold. - - test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| { - env.create_simple_region_hierarchy(); - let t_rptr_free1 = env.t_rptr_free(1); - let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub( - env.t_fn(&[t_rptr_free1], env.tcx().types.isize), - env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), - ); - }) -} - #[test] fn sub_bound_free_true() { //! Test that: @@ -508,25 +476,6 @@ fn sub_bound_free_true() { }) } -#[test] -fn sub_free_bound_false_infer() { - //! Test that: - //! - //! fn(_#1) <: for<'b> fn(&'b isize) - //! - //! does NOT hold for any instantiation of `_#1`. - - test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { - let t_infer1 = env.infcx - .next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP)); - let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub( - env.t_fn(&[t_infer1], env.tcx().types.isize), - env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), - ); - }) -} - /// Test substituting a bound region into a function, which introduces another level of binding. /// This requires adjusting the Debruijn index. #[test] From 94123f26732b7dec975f3f2ae9ba1ec536a711d3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Fri, 16 Nov 2018 19:13:55 -0500 Subject: [PATCH 106/124] make `get_highlight_region_for_regionvid` only affect re-vid In NLL, ReVid is all there is, but I might want to repurpose. --- src/librustc/util/ppaux.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 318d7adb19011..cbba4181271fd 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -771,7 +771,7 @@ define_print! { define_print! { () ty::RegionKind, (self, f, cx) { display { - if cx.is_verbose || get_highlight_region_for_regionvid().is_some() { + if cx.is_verbose { return self.print_debug(f, cx); } @@ -806,11 +806,16 @@ define_print! { ), } } - ty::ReVar(region_vid) if cx.identify_regions => { - write!(f, "'{}rv", region_vid.index()) + ty::ReVar(region_vid) => { + if get_highlight_region_for_regionvid().is_some() { + write!(f, "{:?}", region_vid) + } else if cx.identify_regions { + write!(f, "'{}rv", region_vid.index()) + } else { + Ok(()) + } } ty::ReScope(_) | - ty::ReVar(_) | ty::ReErased => Ok(()), ty::ReStatic => write!(f, "'static"), ty::ReEmpty => write!(f, "'<empty>"), From d354e850ba6dd8f703e1c6d63af74b4243eaf116 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sat, 17 Nov 2018 06:10:30 -0500 Subject: [PATCH 107/124] dump out the exact state in error reporting debugs --- src/librustc/infer/error_reporting/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index e34bb9f4f7bd9..be1ec553b9f5a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1306,6 +1306,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (&sup_origin, &sub_origin) { (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => { + debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); + debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); + debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); + debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); + debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); + debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); + debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); + debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); + debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values); + if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = ( self.values_str(&sup_trace.values), self.values_str(&sub_trace.values), From b41285158b1772854147049241ec0a983653970a Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sat, 17 Nov 2018 06:27:44 -0500 Subject: [PATCH 108/124] generalize region highlights into a struct --- src/librustc/util/ppaux.rs | 124 +++++++++++------- .../borrow_check/error_reporting.rs | 10 +- .../error_reporting/region_name.rs | 9 +- 3 files changed, 91 insertions(+), 52 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index cbba4181271fd..ea0495c5c738c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -21,17 +21,87 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; use hir; +/// The "region highlights" are used to control region printing during +/// specific error messages. When a "region highlight" is enabled, it +/// gives an alternate way to print specific regions. For now, we +/// always print those regions using a number, so something like `'0`. +/// +/// Regions not selected by the region highlight mode are presently +/// unaffected. +#[derive(Copy, Clone, Default)] +pub struct RegionHighlightMode { + /// If enabled, when we see the selected region inference + /// variable, use `"'N"`; otherwise, use an empty string `""` + /// (which is our ordinary behavior). + highlight_region_vid: Option<(RegionVid, usize)>, + + /// If enabled, when printing a "free region" that originated from + /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily + /// have names print as normal. + /// + /// This is used when you have a signature like `fn foo(x: &u32, + /// y: &'a u32)` and we want to give a name to the region of the + /// reference `x`. + highlight_bound_region: Option<(ty::BoundRegion, usize)>, +} + thread_local! { /// Mechanism for highlighting of specific regions for display in NLL region inference errors. /// Contains region to highlight and counter for number to use when highlighting. - static HIGHLIGHT_REGION_FOR_REGIONVID: Cell<Option<(RegionVid, usize)>> = Cell::new(None) + static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> = + Cell::new(RegionHighlightMode::default()) } -thread_local! { - /// Mechanism for highlighting of specific regions for display in NLL's 'borrow does not live - /// long enough' errors. Contains a region to highlight and a counter to use. - static HIGHLIGHT_REGION_FOR_BOUND_REGION: Cell<Option<(ty::BoundRegion, usize)>> = - Cell::new(None) +impl RegionHighlightMode { + pub fn get() -> Self { + REGION_HIGHLIGHT_MODE.with(|c| c.get()) + } + + fn set<R>( + old_mode: Self, + new_mode: Self, + op: impl FnOnce() -> R, + ) -> R { + REGION_HIGHLIGHT_MODE.with(|c| { + c.set(new_mode); + let result = op(); + c.set(old_mode); + result + }) + } + + pub fn highlighting_region_vid<R>(vid: RegionVid, number: usize, op: impl FnOnce() -> R) -> R { + let old_mode = Self::get(); + assert!(old_mode.highlight_region_vid.is_none()); + Self::set( + old_mode, + Self { + highlight_region_vid: Some((vid, number)), + ..old_mode + }, + op, + ) + } + + /// During the execution of `op`, highlight the given bound + /// region. We can only highlight one bound region at a time. See + /// the field `highlight_bound_region` for more detailed notes. + pub fn highlighting_bound_region<R>( + br: ty::BoundRegion, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + let old_mode = Self::get(); + assert!(old_mode.highlight_bound_region.is_none()); + Self::set( + old_mode, + Self { + highlight_bound_region: Some((br, number)), + ..old_mode + }, + op, + ) + } } macro_rules! gen_display_debug_body { @@ -553,42 +623,6 @@ pub fn parameterized<F: fmt::Write>(f: &mut F, PrintContext::new().parameterized(f, substs, did, projections) } -fn get_highlight_region_for_regionvid() -> Option<(RegionVid, usize)> { - HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| hr.get()) -} - -pub fn with_highlight_region_for_regionvid<R>( - r: RegionVid, - counter: usize, - op: impl FnOnce() -> R -) -> R { - HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| { - assert_eq!(hr.get(), None); - hr.set(Some((r, counter))); - let r = op(); - hr.set(None); - r - }) -} - -fn get_highlight_region_for_bound_region() -> Option<(ty::BoundRegion, usize)> { - HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| hr.get()) -} - -pub fn with_highlight_region_for_bound_region<R>( - r: ty::BoundRegion, - counter: usize, - op: impl Fn() -> R -) -> R { - HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| { - assert_eq!(hr.get(), None); - hr.set(Some((r, counter))); - let r = op(); - hr.set(None); - r - }) -} - impl<'a, T: Print> Print for &'a T { fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { (*self).print(f, cx) @@ -740,7 +774,7 @@ define_print! { return self.print_debug(f, cx); } - if let Some((region, counter)) = get_highlight_region_for_bound_region() { + if let Some((region, counter)) = RegionHighlightMode::get().highlight_bound_region { if *self == region { return match *self { BrNamed(_, name) => write!(f, "{}", name), @@ -807,7 +841,7 @@ define_print! { } } ty::ReVar(region_vid) => { - if get_highlight_region_for_regionvid().is_some() { + if RegionHighlightMode::get().highlight_region_vid.is_some() { write!(f, "{:?}", region_vid) } else if cx.identify_regions { write!(f, "'{}rv", region_vid.index()) @@ -944,7 +978,7 @@ impl fmt::Debug for ty::FloatVid { impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some((region, counter)) = get_highlight_region_for_regionvid() { + if let Some((region, counter)) = RegionHighlightMode::get().highlight_region_vid { debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter); return if *self == region { write!(f, "'{:?}", counter) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 6a5b5d172bbe4..83cd28bbdc58c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -12,7 +12,7 @@ use rustc::mir::{ TerminatorKind, VarBindingForm, }; use rustc::ty::{self, DefIdTree}; -use rustc::util::ppaux::with_highlight_region_for_bound_region; +use rustc::util::ppaux::RegionHighlightMode; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -2177,7 +2177,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, - ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()), + ) => RegionHighlightMode::highlighting_bound_region(*br, counter, || ty.to_string()), _ => ty.to_string(), } } @@ -2189,7 +2189,11 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::TyKind::Ref(region, _, _) => match region { ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { - with_highlight_region_for_bound_region(*br, counter, || region.to_string()) + RegionHighlightMode::highlighting_bound_region( + *br, + counter, + || region.to_string(), + ) } _ => region.to_string(), }, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 963d4ab3a5466..bff8015511242 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -8,7 +8,7 @@ use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; -use rustc::util::ppaux::with_highlight_region_for_regionvid; +use rustc::util::ppaux::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; @@ -396,7 +396,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_ty: Ty<'tcx>, counter: &mut usize, ) -> Option<RegionName> { - let type_name = with_highlight_region_for_regionvid(needle_fr, *counter, || { + let type_name = RegionHighlightMode::highlighting_region_vid(needle_fr, *counter, || { infcx.extract_type_name(&argument_ty) }); @@ -673,8 +673,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { return None; } - let type_name = with_highlight_region_for_regionvid( - fr, *counter, || infcx.extract_type_name(&return_ty)); + let type_name = RegionHighlightMode::highlighting_region_vid( + fr, *counter, || infcx.extract_type_name(&return_ty), + ); let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir"); From 749b6fb42b862da1e5f7683de8ba26addd18a1a9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sat, 17 Nov 2018 07:03:26 -0500 Subject: [PATCH 109/124] add the ability to highlight placeholders --- src/librustc/util/ppaux.rs | 83 +++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ea0495c5c738c..55e3f3e6f930a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -43,6 +43,13 @@ pub struct RegionHighlightMode { /// y: &'a u32)` and we want to give a name to the region of the /// reference `x`. highlight_bound_region: Option<(ty::BoundRegion, usize)>, + + /// If enabled, when printing a "placeholder" (what we get when + /// substituting a universally quantified region as in `for<'a> T: + /// Foo<'a>`), print out instead `'N`. + /// + /// (Unlike other modes, we can highlight more than one placeholder at a time.) + highlight_placeholders: [Option<(ty::PlaceholderRegion, usize)>; 2], } thread_local! { @@ -53,10 +60,12 @@ thread_local! { } impl RegionHighlightMode { + /// Read and return current region highlight settings (accesses thread-local state).a pub fn get() -> Self { REGION_HIGHLIGHT_MODE.with(|c| c.get()) } + /// Internal helper to update current settings during the execution of `op`. fn set<R>( old_mode: Self, new_mode: Self, @@ -70,6 +79,9 @@ impl RegionHighlightMode { }) } + /// During the execution of `op`, highlight the region inference + /// vairable `vid` as `'N`. We can only highlight one region vid + /// at a time. pub fn highlighting_region_vid<R>(vid: RegionVid, number: usize, op: impl FnOnce() -> R) -> R { let old_mode = Self::get(); assert!(old_mode.highlight_region_vid.is_none()); @@ -102,6 +114,52 @@ impl RegionHighlightMode { op, ) } + + /// During the execution of `op`, highlight the given placeholders + /// with the given numbers. Unlike other modes: non-highlighted + /// placeholders are printed as `'_` (where they might normally print + /// differently. This may want to be tweaked; but we do it for two reasons + /// + /// (a) to draw attention to the placeholders we are trying to highlight + /// (b) because placeholder names can come from other scopes than the one + /// in which the error occurred, so that can be misleading. + /// + /// We can highlight up to two placeholders at a time. + pub fn highlighting_placeholder<R>( + placeholder: ty::PlaceholderRegion, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + let old_mode = Self::get(); + let mut new_mode = old_mode; + let first_avail_slot = new_mode.highlight_placeholders.iter_mut() + .filter(|s| s.is_none()) + .next() + .unwrap_or_else(|| { + panic!( + "can only highlight {} placeholders at a time", + old_mode.highlight_placeholders.len(), + ) + }); + *first_avail_slot = Some((placeholder, number)); + Self::set(old_mode, new_mode, op) + } + + /// Returns true if any placeholders are highlighted. + pub fn any_placeholders_highlighted(&self) -> bool { + self.highlight_placeholders.iter().any(|p| p.is_some()) + } + + /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. + pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> { + self.highlight_placeholders + .iter() + .filter_map(|h| match h { + &Some((h, n)) if h == p => Some(n), + _ => None, + }) + .next() + } } macro_rules! gen_display_debug_body { @@ -802,6 +860,25 @@ define_print! { } } +define_print! { + () ty::PlaceholderRegion, (self, f, cx) { + display { + if cx.is_verbose { + return self.print_debug(f, cx); + } + + let highlight = RegionHighlightMode::get(); + if let Some(counter) = highlight.placeholder_highlight(*self) { + write!(f, "'{}", counter) + } else if highlight.any_placeholders_highlighted() { + write!(f, "'_") + } else { + write!(f, "{}", self.name) + } + } + } +} + define_print! { () ty::RegionKind, (self, f, cx) { display { @@ -818,10 +895,12 @@ define_print! { write!(f, "{}", data.name) } ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { write!(f, "{}", br) } + ty::RePlaceholder(p) => { + write!(f, "{}", p) + } ty::ReScope(scope) if cx.identify_regions => { match scope.data { region::ScopeData::Node => From b53e7e39a24f707635ef4f64480b6d4a825d6a4c Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sat, 17 Nov 2018 08:18:37 -0500 Subject: [PATCH 110/124] introduce placeholder-placeholder errors for trait matching --- src/librustc/infer/error_reporting/mod.rs | 3 +- .../error_reporting/nice_region_error/mod.rs | 8 +- .../nice_region_error/outlives_closure.rs | 3 +- .../nice_region_error/placeholder_error.rs | 223 ++++++++++++++++++ .../nice_region_error/static_impl_trait.rs | 1 + .../infer/lexical_region_resolve/mod.rs | 8 +- .../associated-types-eq-hr.rs | 8 +- .../associated-types-eq-hr.stderr | 63 ++--- src/test/ui/generator/auto-trait-regions.rs | 3 +- .../ui/generator/auto-trait-regions.stderr | 26 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 11 +- .../hrtb-exists-forall-trait-invariant.rs | 2 +- .../hrtb-exists-forall-trait-invariant.stderr | 13 +- 13 files changed, 273 insertions(+), 99 deletions(-) create mode 100644 src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index be1ec553b9f5a..d0cb718f55a25 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -339,6 +339,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } RegionResolutionError::SubSupConflict( + _, var_origin, sub_origin, sub_r, @@ -407,7 +408,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { errors.sort_by_key(|u| match *u { RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::SubSupConflict(ref rvo, _, _, _, _) => rvo.span(), + RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), }); errors } diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index ecf59daeaf12e..f7ba546fa7f3b 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -8,6 +8,7 @@ use util::common::ErrorReported; mod different_lifetimes; mod find_anon_type; mod named_anon_conflict; +mod placeholder_error; mod outlives_closure; mod static_impl_trait; mod util; @@ -58,10 +59,11 @@ impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. self.try_report_named_anon_conflict() + .or_else(|| self.try_report_placeholder_conflict()) } pub fn try_report(&self) -> Option<ErrorReported> { - self.try_report_named_anon_conflict() + self.try_report_from_nll() .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_outlives_closure()) .or_else(|| self.try_report_static_impl_trait()) @@ -69,8 +71,8 @@ impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) { match (&self.error, self.regions) { - (&Some(ConcreteFailure(ref origin, sub, sup)), None) => (origin.span(), sub, sup), - (&Some(SubSupConflict(_, ref origin, sub, _, sup)), None) => (origin.span(), sub, sup), + (Some(ConcreteFailure(origin, sub, sup)), None) => (origin.span(), sub, sup), + (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => (origin.span(), sub, sup), (None, Some((span, sub, sup))) => (span, sub, sup), (Some(_), Some(_)) => panic!("incorrectly built NiceRegionError"), _ => panic!("trying to report on an incorrect lifetime failure"), diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index 789796d95cb14..c4c71037d8b35 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -36,7 +36,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// ...because it cannot outlive this closure /// ``` pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> { - if let Some(SubSupConflict(origin, + if let Some(SubSupConflict(_, + origin, ref sub_origin, _, ref sup_origin, diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs new file mode 100644 index 0000000000000..f5e9f3814b467 --- /dev/null +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -0,0 +1,223 @@ +use hir::def_id::DefId; +use infer::error_reporting::nice_region_error::NiceRegionError; +use infer::lexical_region_resolve::RegionResolutionError; +use infer::ValuePairs; +use infer::{SubregionOrigin, TypeTrace}; +use traits::{ObligationCause, ObligationCauseCode}; +use ty; +use ty::error::ExpectedFound; +use ty::subst::Substs; +use util::common::ErrorReported; +use util::ppaux::RegionHighlightMode; + +impl NiceRegionError<'me, 'gcx, 'tcx> { + /// When given a `ConcreteFailure` for a function with arguments containing a named region and + /// an anonymous region, emit an descriptive diagnostic error. + pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> { + // Check for the first case: relating two trait-refs, and we + // find a conflict between two placeholders. + match &self.error { + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + ty::RePlaceholder(sub_placeholder), + _, + ty::RePlaceholder(sup_placeholder), + )) => if expected.def_id == found.def_id { + return Some(self.try_report_two_placeholders_trait( + Some(*vid), + cause, + Some(*sub_placeholder), + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )); + } else { + // I actually can't see why this would be the case ever. + }, + + _ => {} + } + + None + } + + // error[E0308]: implementation of `Foo` does not apply to enough lifetimes + // --> /home/nmatsakis/tmp/foo.rs:12:5 + // | + // 12 | all::<&'static u32>(); + // | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + // | + // = note: Due to a where-clause on the function `all`, + // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. + // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. + fn try_report_two_placeholders_trait( + &self, + vid: Option<ty::RegionVid>, + cause: &ObligationCause<'tcx>, + sub_placeholder: Option<ty::PlaceholderRegion>, + sup_placeholder: Option<ty::PlaceholderRegion>, + trait_def_id: DefId, + expected_substs: &'tcx Substs<'tcx>, + actual_substs: &'tcx Substs<'tcx>, + ) -> ErrorReported { + let mut err = self.tcx.sess.struct_span_err( + cause.span(&self.tcx), + &format!( + "implementation of `{}` is not general enough", + self.tcx.item_path_str(trait_def_id), + ), + ); + + match cause.code { + ObligationCauseCode::ItemObligation(def_id) => { + err.note(&format!( + "Due to a where-clause on `{}`,", + self.tcx.item_path_str(def_id), + )); + } + _ => (), + } + + let expected_trait_ref = ty::TraitRef { + def_id: trait_def_id, + substs: expected_substs, + }; + let actual_trait_ref = ty::TraitRef { + def_id: trait_def_id, + substs: actual_substs, + }; + + // Search the expected and actual trait references to see (a) + // whether the sub/sup placeholders appear in them (sometimes + // you have a trait ref like `T: Foo<fn(&u8)>`, where the + // placeholder was created as part of an inner type) and (b) + // whether the inference variable appears. In each case, + // assign a counter value in each case if so. + let mut counter = 0; + let mut has_sub = None; + let mut has_sup = None; + let mut has_vid = None; + + self.tcx + .for_each_free_region(&expected_trait_ref, |r| match r { + ty::RePlaceholder(p) => { + if Some(*p) == sub_placeholder { + if has_sub.is_none() { + has_sub = Some(counter); + counter += 1; + } + } else if Some(*p) == sup_placeholder { + if has_sup.is_none() { + has_sup = Some(counter); + counter += 1; + } + } + } + _ => {} + }); + + self.tcx + .for_each_free_region(&actual_trait_ref, |r| match r { + ty::ReVar(v) if Some(*v) == vid => { + if has_vid.is_none() { + has_vid = Some(counter); + counter += 1; + } + } + _ => {} + }); + + maybe_highlight( + sub_placeholder, + has_sub, + RegionHighlightMode::highlighting_placeholder, + || { + maybe_highlight( + sup_placeholder, + has_sup, + RegionHighlightMode::highlighting_placeholder, + || match (has_sub, has_sup) { + (Some(n1), Some(n2)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any two lifetimes `'{}` and `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + )); + } + (Some(n), _) | (_, Some(n)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any lifetime `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + n, + )); + } + (None, None) => { + err.note(&format!( + "`{}` must implement `{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + )); + } + }, + ) + }, + ); + + maybe_highlight( + vid, + has_vid, + RegionHighlightMode::highlighting_region_vid, + || match has_vid { + Some(n) => { + err.note(&format!( + "but `{}` only implements `{}` for some lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } + None => { + err.note(&format!( + "but `{}` only implements `{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + )); + } + }, + ); + + err.emit(); + ErrorReported + } +} + +/// If both `thing` and `counter` are `Some`, invoke +/// `highlighting_func` with their contents (and the `op`). Else just +/// invoke `op`. +fn maybe_highlight<T, F, R>( + thing: Option<T>, + counter: Option<usize>, + highlighting_func: impl FnOnce(T, usize, F) -> R, + op: F, +) -> R +where + F: FnOnce() -> R, +{ + if let Some(thing) = thing { + if let Some(n) = counter { + return highlighting_func(thing, n, op); + } + } + op() +} diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 6d2d2ee93ab50..9fc3bb05cdab1 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -11,6 +11,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> { if let Some(ref error) = self.error { if let RegionResolutionError::SubSupConflict( + _, var_origin, sub_origin, sub_r, diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index bbab17f951659..dbf8f270ab0c9 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -73,12 +73,13 @@ pub enum RegionResolutionError<'tcx> { /// `a` (but none of the known bounds are sufficient). GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>), - /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`: + /// `SubSupConflict(v, v_origin, sub_origin, sub_r, sup_origin, sup_r)`: /// - /// Could not infer a value for `v` because `sub_r <= v` (due to - /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and + /// Could not infer a value for `v` (which has origin `v_origin`) + /// because `sub_r <= v` (due to `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and /// `sub_r <= sup_r` does not hold. SubSupConflict( + RegionVid, RegionVariableOrigin, SubregionOrigin<'tcx>, Region<'tcx>, @@ -596,6 +597,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { origin, node_idx, lower_bound.region, upper_bound.region ); errors.push(RegionResolutionError::SubSupConflict( + node_idx, origin, lower_bound.origin.clone(), lower_bound.region, diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index bc7888f74af22..20fa1e7a48db1 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -89,14 +89,12 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::<Tuple>(); - //~^ ERROR E0495 - //~| ERROR E0495 + //~^ ERROR not general enough } pub fn call_tuple_two() { tuple_two::<Tuple>(); - //~^ ERROR E0495 - //~| ERROR E0495 + //~^ ERROR not general enough } pub fn call_tuple_three() { @@ -105,7 +103,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::<Tuple>(); - //~^ ERROR E0495 + //~^ ERROR not general enough } fn main() { } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 226733da0f63f..d3eaa894b5043 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -34,67 +34,36 @@ LL | | // ok for UintStruct, but not IntStruct LL | | } | |_^ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:91:5 | LL | tuple_one::<Tuple>(); | ^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:20), 'x) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:21), 'y) })... - = note: ...so that the types are compatible: - expected TheTrait<(&'x isize, &'y isize)> - found TheTrait<(&isize, &isize)> + = note: Due to a where-clause on `tuple_one`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/associated-types-eq-hr.rs:91:5 - | -LL | tuple_one::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ - | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:20), 'x) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:21), 'y) })... - = note: ...so that the types are compatible: - expected TheTrait<(&'x isize, &'y isize)> - found TheTrait<(&isize, &isize)> - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/associated-types-eq-hr.rs:97:5 - | -LL | tuple_two::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ - | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:23), 'x) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:24), 'y) })... - = note: ...so that the types are compatible: - expected TheTrait<(&'x isize, &'y isize)> - found TheTrait<(&isize, &isize)> - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/associated-types-eq-hr.rs:97:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | LL | tuple_two::<Tuple>(); | ^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:23), 'x) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:24), 'y) })... - = note: ...so that the types are compatible: - expected TheTrait<(&'x isize, &'y isize)> - found TheTrait<(&isize, &isize)> + = note: Due to a where-clause on `tuple_two`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/associated-types-eq-hr.rs:107:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:105:5 | LL | tuple_four::<Tuple>(); | ^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:28), 'x) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:29), 'y) })... - = note: ...so that the types are compatible: - expected TheTrait<(&'x isize, &'y isize)> - found TheTrait<(&isize, &isize)> + = note: Due to a where-clause on `tuple_four`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors occurred: E0271, E0495. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index 4523e05696a2b..5b52bf3cd04b9 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -47,6 +47,5 @@ fn main() { assert_foo(a); }; assert_foo(gen); - //~^ ERROR E0495 - //~| ERROR E0495 + //~^ ERROR not general enough } diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 3998ffe2522b4..6f748a740328a 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -20,31 +20,15 @@ LL | assert_foo(gen); = note: lifetime RePlaceholder(Placeholder { universe: U35, name: BrAnon(1) })... = note: ...does not necessarily outlive the static lifetime -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:49:5 | LL | assert_foo(gen); | ^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U47, name: BrAnon(2) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U47, name: BrAnon(1) })... - = note: ...so that the types are compatible: - expected Foo - found Foo + = note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1` + = note: but `A<'_, '2>` only implements `Foo` for some lifetime `'2` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/auto-trait-regions.rs:49:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^ - | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U51, name: BrAnon(2) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U51, name: BrAnon(1) })... - = note: ...so that the types are compatible: - expected Foo - found Foo - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors occurred: E0308, E0495. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 24d374e470e32..2ee398e3dd3b2 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,15 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:28:10 | LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'a) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:12), 'b) })... - = note: ...so that the types are compatible: - expected Foo<(&'a isize, &'b isize)> - found Foo<(&isize, &isize)> + = note: Due to a where-clause on `want_foo2`, + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index db589548d0e8e..da3f8ad1b8957 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR cannot infer + foo::<()>(); //~ ERROR not general enough } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 7a0986ccdd939..6a61181e2407c 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,15 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | foo::<()>(); //~ ERROR cannot infer +LL | foo::<()>(); //~ ERROR not general enough | ^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })... - = note: ...so that the types are compatible: - expected Trait<for<'b> fn(std::cell::Cell<&'b u32>)> - found Trait<fn(std::cell::Cell<&u32>)> + = note: Due to a where-clause on `foo`, + = note: `()` must implement `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` + = note: but `()` only implements `Trait<fn(std::cell::Cell<&'0 u32>)>` for some lifetime `'0` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. From d3a8d6dfaf8067d55d82c59c8f58cd6b3d5169ee Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sun, 18 Nov 2018 13:25:53 -0500 Subject: [PATCH 111/124] apply the new placeholder errors even with just one placeholder --- .../nice_region_error/placeholder_error.rs | 52 ++++++++++++++++++- .../ui/hrtb/hrtb-cache-issue-54302.stderr | 10 ++-- src/test/ui/hrtb/hrtb-just-for-static.rs | 6 +++ src/test/ui/hrtb/hrtb-just-for-static.stderr | 12 ++++- src/test/ui/issues/issue-54302-cases.rs | 8 +-- src/test/ui/issues/issue-54302-cases.stderr | 37 +++++-------- src/test/ui/issues/issue-54302.rs | 2 +- src/test/ui/issues/issue-54302.stderr | 10 ++-- 8 files changed, 90 insertions(+), 47 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index f5e9f3814b467..83fe3da70775d 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -28,7 +28,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { _, ty::RePlaceholder(sup_placeholder), )) => if expected.def_id == found.def_id { - return Some(self.try_report_two_placeholders_trait( + return Some(self.try_report_placeholders_trait( Some(*vid), cause, Some(*sub_placeholder), @@ -41,6 +41,54 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { // I actually can't see why this would be the case ever. }, + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + ty::RePlaceholder(sub_placeholder), + _, + _, + )) => if expected.def_id == found.def_id { + return Some(self.try_report_placeholders_trait( + Some(*vid), + cause, + Some(*sub_placeholder), + None, + expected.def_id, + expected.substs, + found.substs, + )); + } else { + // I actually can't see why this would be the case ever. + }, + + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + _, + _, + ty::RePlaceholder(sup_placeholder), + )) => if expected.def_id == found.def_id { + return Some(self.try_report_placeholders_trait( + Some(*vid), + cause, + None, + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )); + } else { + // I actually can't see why this would be the case ever. + }, + _ => {} } @@ -56,7 +104,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { // = note: Due to a where-clause on the function `all`, // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. - fn try_report_two_placeholders_trait( + fn try_report_placeholders_trait( &self, vid: Option<ty::RegionVid>, cause: &ObligationCause<'tcx>, diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index 940a6e3f06853..e82fa51524ef1 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -1,15 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements +error: implementation of `Deserialize` is not general enough --> $DIR/hrtb-cache-issue-54302.rs:19:5 | LL | assert_deserialize_owned::<&'static str>(); //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'de) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Deserialize<'de> - found Deserialize<'_> + = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` + = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs index 3aee241ccd2d7..88d5ce8e64056 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.rs +++ b/src/test/ui/hrtb/hrtb-just-for-static.rs @@ -24,4 +24,10 @@ fn give_static() { want_hrtb::<StaticInt>() //~ ERROR } +// AnyInt implements Foo<&'a isize> for any 'a, so it is a match. +impl<'a> Foo<&'a isize> for &'a u32 { } +fn give_some<'a>() { + want_hrtb::<&'a u32>() //~ ERROR +} + fn main() { } diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index d3c2f7d059a6f..6ea415c1734b2 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -9,6 +9,16 @@ LL | want_hrtb::<StaticInt>() //~ ERROR = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'a) })... = note: ...does not necessarily outlive the static lifetime -error: aborting due to previous error +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: Due to a where-clause on `want_hrtb`, + = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` + = note: but `&'1 u32` only implements `Foo<&'1 isize>` for some lifetime `'1` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-54302-cases.rs b/src/test/ui/issues/issue-54302-cases.rs index 286d37b182e31..faa116269ee96 100644 --- a/src/test/ui/issues/issue-54302-cases.rs +++ b/src/test/ui/issues/issue-54302-cases.rs @@ -61,25 +61,25 @@ impl<T> RefFoo<T> for T where for<'a> &'a T: Foo<'static, T> { fn coerce_lifetime1(a: &u32) -> &'static u32 { <u32 as RefFoo<u32>>::ref_foo(a) - //~^ ERROR cannot infer + //~^ ERROR not general enough } fn coerce_lifetime2(a: &i32) -> &'static i32 { <i32 as RefFoo<i32>>::ref_foo(a) - //~^ ERROR cannot infer + //~^ ERROR not general enough } fn coerce_lifetime3(a: &u64) -> &'static u64 { <u64 as RefFoo<u64>>::ref_foo(a) - //~^ ERROR cannot infer + //~^ ERROR not general enough } fn coerce_lifetime4(a: &i64) -> &'static i64 { <i64 as RefFoo<i64>>::ref_foo(a) - //~^ ERROR cannot infer + //~^ ERROR not general enough } fn main() {} diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 09a4e091d2bcf..6469829e789b4 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -1,51 +1,38 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | LL | <u32 as RefFoo<u32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Foo<'static, u32> - found Foo<'_, u32> + = note: `&'0 u32` must implement `Foo<'static, u32>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | LL | <i32 as RefFoo<i32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Foo<'static, i32> - found Foo<'_, i32> + = note: `&'0 i32` must implement `Foo<'static, i32>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | LL | <u64 as RefFoo<u64>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Foo<'static, u64> - found Foo<'_, u64> + = note: `&'0 u64` must implement `Foo<'static, u64>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | LL | <i64 as RefFoo<i64>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:27), 'a) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Foo<'static, i64> - found Foo<'_, i64> + = note: `&'0 i64` must implement `Foo<'static, i64>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-54302.rs b/src/test/ui/issues/issue-54302.rs index 35cdc73a78fd0..1bfaebc3895d9 100644 --- a/src/test/ui/issues/issue-54302.rs +++ b/src/test/ui/issues/issue-54302.rs @@ -11,7 +11,7 @@ fn main() { // Then why does it implement DeserializeOwned? This compiles. fn assert_deserialize_owned<T: DeserializeOwned>() {} assert_deserialize_owned::<&'static str>(); - //~^ ERROR E0495 + //~^ ERROR not general enough // It correctly does not implement for<'de> Deserialize<'de>. //fn assert_hrtb<T: for<'de> Deserialize<'de>>() {} diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index b456d2582ffd6..1b255204b6ef7 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -1,15 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements +error: implementation of `Deserialize` is not general enough --> $DIR/issue-54302.rs:13:5 | LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'de) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the types are compatible: - expected Deserialize<'de> - found Deserialize<'_> + = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` + = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. From 3744f87564ba417a449f3b10f37fe1c385f49d7c Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sun, 18 Nov 2018 15:25:57 -0500 Subject: [PATCH 112/124] refactor highlighting to take any RegionKind, making it more general --- .../nice_region_error/placeholder_error.rs | 197 +++++++----------- src/librustc/util/ppaux.rs | 150 +++++++------ 2 files changed, 160 insertions(+), 187 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 83fe3da70775d..4fd1a97007682 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -24,15 +24,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), - ty::RePlaceholder(sub_placeholder), + sub_placeholder @ ty::RePlaceholder(_), _, - ty::RePlaceholder(sup_placeholder), + sup_placeholder @ ty::RePlaceholder(_), )) => if expected.def_id == found.def_id { return Some(self.try_report_placeholders_trait( - Some(*vid), + Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, - Some(*sub_placeholder), - Some(*sup_placeholder), + Some(sub_placeholder), + Some(sup_placeholder), expected.def_id, expected.substs, found.substs, @@ -48,14 +48,14 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), - ty::RePlaceholder(sub_placeholder), + sub_placeholder @ ty::RePlaceholder(_), _, _, )) => if expected.def_id == found.def_id { return Some(self.try_report_placeholders_trait( - Some(*vid), + Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, - Some(*sub_placeholder), + Some(sub_placeholder), None, expected.def_id, expected.substs, @@ -74,10 +74,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }), _, _, - ty::RePlaceholder(sup_placeholder), + sup_placeholder @ ty::RePlaceholder(_), )) => if expected.def_id == found.def_id { return Some(self.try_report_placeholders_trait( - Some(*vid), + Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, None, Some(*sup_placeholder), @@ -106,10 +106,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. fn try_report_placeholders_trait( &self, - vid: Option<ty::RegionVid>, + vid: Option<ty::Region<'tcx>>, cause: &ObligationCause<'tcx>, - sub_placeholder: Option<ty::PlaceholderRegion>, - sup_placeholder: Option<ty::PlaceholderRegion>, + sub_placeholder: Option<ty::Region<'tcx>>, + sup_placeholder: Option<ty::Region<'tcx>>, trait_def_id: DefId, expected_substs: &'tcx Substs<'tcx>, actual_substs: &'tcx Substs<'tcx>, @@ -152,120 +152,75 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut has_sup = None; let mut has_vid = None; - self.tcx - .for_each_free_region(&expected_trait_ref, |r| match r { - ty::RePlaceholder(p) => { - if Some(*p) == sub_placeholder { - if has_sub.is_none() { - has_sub = Some(counter); - counter += 1; - } - } else if Some(*p) == sup_placeholder { - if has_sup.is_none() { - has_sup = Some(counter); - counter += 1; - } - } - } - _ => {} - }); + self.tcx.for_each_free_region(&expected_trait_ref, |r| { + if Some(r) == sub_placeholder && has_sub.is_none() { + has_sub = Some(counter); + counter += 1; + } else if Some(r) == sup_placeholder && has_sup.is_none() { + has_sup = Some(counter); + counter += 1; + } + }); - self.tcx - .for_each_free_region(&actual_trait_ref, |r| match r { - ty::ReVar(v) if Some(*v) == vid => { - if has_vid.is_none() { - has_vid = Some(counter); - counter += 1; + self.tcx.for_each_free_region(&actual_trait_ref, |r| { + if Some(r) == vid && has_vid.is_none() { + has_vid = Some(counter); + counter += 1; + } + }); + + RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { + RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { + match (has_sub, has_sup) { + (Some(n1), Some(n2)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any two lifetimes `'{}` and `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + )); + } + (Some(n), _) | (_, Some(n)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any lifetime `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + n, + )); + } + (None, None) => { + err.note(&format!( + "`{}` must implement `{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + )); } } - _ => {} - }); - - maybe_highlight( - sub_placeholder, - has_sub, - RegionHighlightMode::highlighting_placeholder, - || { - maybe_highlight( - sup_placeholder, - has_sup, - RegionHighlightMode::highlighting_placeholder, - || match (has_sub, has_sup) { - (Some(n1), Some(n2)) => { - err.note(&format!( - "`{}` must implement `{}` \ - for any two lifetimes `'{}` and `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - )); - } - (Some(n), _) | (_, Some(n)) => { - err.note(&format!( - "`{}` must implement `{}` \ - for any lifetime `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - n, - )); - } - (None, None) => { - err.note(&format!( - "`{}` must implement `{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - )); - } - }, - ) - }, - ); + }) + }); - maybe_highlight( - vid, - has_vid, - RegionHighlightMode::highlighting_region_vid, - || match has_vid { - Some(n) => { - err.note(&format!( - "but `{}` only implements `{}` for some lifetime `'{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - n - )); - } - None => { - err.note(&format!( - "but `{}` only implements `{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - )); - } - }, - ); + RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { + Some(n) => { + err.note(&format!( + "but `{}` only implements `{}` for some lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } + None => { + err.note(&format!( + "but `{}` only implements `{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + )); + } + }); err.emit(); ErrorReported } } - -/// If both `thing` and `counter` are `Some`, invoke -/// `highlighting_func` with their contents (and the `op`). Else just -/// invoke `op`. -fn maybe_highlight<T, F, R>( - thing: Option<T>, - counter: Option<usize>, - highlighting_func: impl FnOnce(T, usize, F) -> R, - op: F, -) -> R -where - F: FnOnce() -> R, -{ - if let Some(thing) = thing { - if let Some(n) = counter { - return highlighting_func(thing, n, op); - } - } - op() -} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 55e3f3e6f930a..0742d0aebe954 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; +use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; use std::cell::Cell; @@ -30,10 +30,9 @@ use hir; /// unaffected. #[derive(Copy, Clone, Default)] pub struct RegionHighlightMode { - /// If enabled, when we see the selected region inference - /// variable, use `"'N"`; otherwise, use an empty string `""` - /// (which is our ordinary behavior). - highlight_region_vid: Option<(RegionVid, usize)>, + /// If enabled, when we see the selected region, use `"'N"` + /// instead of the ordinary behavior. + highlight_regions: [Option<(ty::RegionKind, usize)>; 3], /// If enabled, when printing a "free region" that originated from /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily @@ -43,13 +42,6 @@ pub struct RegionHighlightMode { /// y: &'a u32)` and we want to give a name to the region of the /// reference `x`. highlight_bound_region: Option<(ty::BoundRegion, usize)>, - - /// If enabled, when printing a "placeholder" (what we get when - /// substituting a universally quantified region as in `for<'a> T: - /// Foo<'a>`), print out instead `'N`. - /// - /// (Unlike other modes, we can highlight more than one placeholder at a time.) - highlight_placeholders: [Option<(ty::PlaceholderRegion, usize)>; 2], } thread_local! { @@ -79,20 +71,72 @@ impl RegionHighlightMode { }) } + /// If `region` and `number` are both `Some`, invoke + /// `highlighting_region`. Otherwise, just invoke `op` directly. + pub fn maybe_highlighting_region<R>( + region: Option<ty::Region<'_>>, + number: Option<usize>, + op: impl FnOnce() -> R, + ) -> R { + if let Some(k) = region { + if let Some(n) = number { + return Self::highlighting_region(k, n, op); + } + } + + op() + } + /// During the execution of `op`, highlight the region inference /// vairable `vid` as `'N`. We can only highlight one region vid /// at a time. - pub fn highlighting_region_vid<R>(vid: RegionVid, number: usize, op: impl FnOnce() -> R) -> R { + pub fn highlighting_region<R>(region: ty::Region<'_>, number: usize, op: impl FnOnce() -> R) -> R { let old_mode = Self::get(); - assert!(old_mode.highlight_region_vid.is_none()); - Self::set( - old_mode, - Self { - highlight_region_vid: Some((vid, number)), - ..old_mode - }, - op, - ) + let mut new_mode = old_mode; + let first_avail_slot = new_mode.highlight_regions.iter_mut() + .filter(|s| s.is_none()) + .next() + .unwrap_or_else(|| { + panic!( + "can only highlight {} placeholders at a time", + old_mode.highlight_regions.len(), + ) + }); + *first_avail_slot = Some((*region, number)); + Self::set(old_mode, new_mode, op) + } + + /// Convenience wrapper for `highlighting_region` + pub fn highlighting_region_vid<R>( + vid: ty::RegionVid, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + Self::highlighting_region(&ty::ReVar(vid), number, op) + } + + /// Returns true if any placeholders are highlighted. + fn any_region_vids_highlighted(&self) -> bool { + Self::get() + .highlight_regions + .iter() + .any(|h| match h { + Some((ty::ReVar(_), _)) => true, + _ => false, + }) + } + + /// Returns `Some(n)` with the number to use for the given region, + /// if any. + fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> { + Self::get() + .highlight_regions + .iter() + .filter_map(|h| match h { + Some((r, n)) if r == region => Some(*n), + _ => None, + }) + .next() } /// During the execution of `op`, highlight the given bound @@ -115,50 +159,20 @@ impl RegionHighlightMode { ) } - /// During the execution of `op`, highlight the given placeholders - /// with the given numbers. Unlike other modes: non-highlighted - /// placeholders are printed as `'_` (where they might normally print - /// differently. This may want to be tweaked; but we do it for two reasons - /// - /// (a) to draw attention to the placeholders we are trying to highlight - /// (b) because placeholder names can come from other scopes than the one - /// in which the error occurred, so that can be misleading. - /// - /// We can highlight up to two placeholders at a time. - pub fn highlighting_placeholder<R>( - placeholder: ty::PlaceholderRegion, - number: usize, - op: impl FnOnce() -> R, - ) -> R { - let old_mode = Self::get(); - let mut new_mode = old_mode; - let first_avail_slot = new_mode.highlight_placeholders.iter_mut() - .filter(|s| s.is_none()) - .next() - .unwrap_or_else(|| { - panic!( - "can only highlight {} placeholders at a time", - old_mode.highlight_placeholders.len(), - ) - }); - *first_avail_slot = Some((placeholder, number)); - Self::set(old_mode, new_mode, op) - } - /// Returns true if any placeholders are highlighted. pub fn any_placeholders_highlighted(&self) -> bool { - self.highlight_placeholders.iter().any(|p| p.is_some()) + Self::get() + .highlight_regions + .iter() + .any(|h| match h { + Some((ty::RePlaceholder(_), _)) => true, + _ => false, + }) } /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> { - self.highlight_placeholders - .iter() - .filter_map(|h| match h { - &Some((h, n)) if h == p => Some(n), - _ => None, - }) - .next() + self.region_highlighted(&ty::RePlaceholder(p)) } } @@ -886,6 +900,11 @@ define_print! { return self.print_debug(f, cx); } + // Watch out for region highlights. + if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { + return write!(f, "'{:?}", n); + } + // These printouts are concise. They do not contain all the information // the user might want to diagnose an error, but there is basically no way // to fit that into a short string. Hence the recommendation to use @@ -920,7 +939,7 @@ define_print! { } } ty::ReVar(region_vid) => { - if RegionHighlightMode::get().highlight_region_vid.is_some() { + if RegionHighlightMode::get().any_region_vids_highlighted() { write!(f, "{:?}", region_vid) } else if cx.identify_regions { write!(f, "'{}rv", region_vid.index()) @@ -1057,12 +1076,11 @@ impl fmt::Debug for ty::FloatVid { impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some((region, counter)) = RegionHighlightMode::get().highlight_region_vid { - debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter); - return if *self == region { - write!(f, "'{:?}", counter) + if RegionHighlightMode::get().any_region_vids_highlighted() { + if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) { + return write!(f, "'{:?}", counter); } else { - write!(f, "'_") + return write!(f, "'_"); } } From deb0366ad0574334e69473f90bb283bf15562faf Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sun, 18 Nov 2018 19:07:38 -0500 Subject: [PATCH 113/124] apply the same logic to ConcreteFailure errors --- .../nice_region_error/placeholder_error.rs | 50 +++++++++++++++++++ src/test/ui/generator/auto-trait-regions.rs | 3 +- .../ui/generator/auto-trait-regions.stderr | 26 +++------- src/test/ui/hrtb/hrtb-just-for-static.stderr | 12 ++--- src/test/ui/where-clauses/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 14 +++--- 6 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 4fd1a97007682..4e59c8c43dc09 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -89,6 +89,56 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { // I actually can't see why this would be the case ever. }, + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { .. }), + ty::RePlaceholder(_), + ty::RePlaceholder(_), + )) => { + // I actually can't see why this would be the case ever. + }, + + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region, + sup_region @ ty::RePlaceholder(_), + )) => if expected.def_id == found.def_id { + return Some(self.try_report_placeholders_trait( + Some(sub_region), + cause, + None, + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )); + } else { + // I actually can't see why this would be the case ever. + }, + + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region @ ty::RePlaceholder(_), + sup_region, + )) => if expected.def_id == found.def_id { + return Some(self.try_report_placeholders_trait( + Some(sup_region), + cause, + None, + Some(*sub_region), + expected.def_id, + expected.substs, + found.substs, + )); + } else { + // I actually can't see why this would be the case ever. + }, + _ => {} } diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index 5b52bf3cd04b9..46d7289943857 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -28,8 +28,7 @@ fn main() { assert_foo(x); }; assert_foo(gen); - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `Foo` is not general enough // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 6f748a740328a..94162cb9e8fb0 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,27 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/auto-trait-regions.rs:30:5 - | -LL | assert_foo(gen); - | ^^^^^^^^^^ lifetime mismatch - | - = note: expected type `Foo` - found type `Foo` - = note: lifetime RePlaceholder(Placeholder { universe: U31, name: BrAnon(1) })... - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types +error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:30:5 | LL | assert_foo(gen); - | ^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^ | - = note: expected type `Foo` - found type `Foo` - = note: lifetime RePlaceholder(Placeholder { universe: U35, name: BrAnon(1) })... - = note: ...does not necessarily outlive the static lifetime + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo` for any lifetime `'0` + = note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for some lifetime `'1` error: implementation of `Foo` is not general enough - --> $DIR/auto-trait-regions.rs:49:5 + --> $DIR/auto-trait-regions.rs:48:5 | LL | assert_foo(gen); | ^^^^^^^^^^ @@ -29,6 +16,5 @@ LL | assert_foo(gen); = note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1` = note: but `A<'_, '2>` only implements `Foo` for some lifetime `'2` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 6ea415c1734b2..ee518b956ab1c 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,13 +1,12 @@ -error[E0308]: mismatched types +error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | LL | want_hrtb::<StaticInt>() //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected type `Foo<&'a isize>` - found type `Foo<&'static isize>` - = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'a) })... - = note: ...does not necessarily outlive the static lifetime + = note: Due to a where-clause on `want_hrtb`, + = note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0` + = note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 @@ -21,4 +20,3 @@ LL | want_hrtb::<&'a u32>() //~ ERROR error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index c69055fe0cc82..0ce38e69f6b0f 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,5 +18,5 @@ fn foo<T>(x: &T) {} fn main() { - foo(&X); //~ ERROR E0308 + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 04d7bbabb2a57..06f3659a5c17d 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,14 +1,12 @@ -error[E0308]: mismatched types +error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); //~ ERROR E0308 - | ^^^ lifetime mismatch +LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough + | ^^^ | - = note: expected type `Bar` - found type `Bar` - = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:10), 'a) })... - = note: ...does not necessarily outlive the static lifetime + = note: Due to a where-clause on `foo`, + = note: `&'0 _` must implement `Bar` for any lifetime `'0` + = note: but `&'1 u32` only implements `Bar` for some lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. From d4fb139731104660bc8c4a5d2495264286f76676 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Sun, 18 Nov 2018 19:13:37 -0500 Subject: [PATCH 114/124] say "the lifetime" instead of "some lifetime" when it feels right In particular, when we want to indicate that there is a connection between the self type and the other types. --- .../nice_region_error/placeholder_error.rs | 27 ++++++++++++++----- .../ui/generator/auto-trait-regions.stderr | 4 +-- src/test/ui/hrtb/hrtb-just-for-static.stderr | 2 +- src/test/ui/issues/issue-54302-cases.stderr | 8 +++--- .../ui/where-clauses/where-for-self-2.stderr | 2 +- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 4e59c8c43dc09..07a61eb6d776e 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -95,7 +95,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { ty::RePlaceholder(_), )) => { // I actually can't see why this would be the case ever. - }, + } Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { @@ -219,6 +219,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } }); + let self_ty_has_vid = self + .tcx + .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); + RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { match (has_sub, has_sup) { @@ -254,12 +258,21 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { Some(n) => { - err.note(&format!( - "but `{}` only implements `{}` for some lifetime `'{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - n - )); + if self_ty_has_vid { + err.note(&format!( + "but `{}` only implements `{}` for the lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } else { + err.note(&format!( + "but `{}` only implements `{}` for some lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } } None => { err.note(&format!( diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 94162cb9e8fb0..1b4dfe2df1c0c 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -5,7 +5,7 @@ LL | assert_foo(gen); | ^^^^^^^^^^ | = note: `&'0 OnlyFooIfStaticRef` must implement `Foo` for any lifetime `'0` - = note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for some lifetime `'1` + = note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for the lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:48:5 @@ -14,7 +14,7 @@ LL | assert_foo(gen); | ^^^^^^^^^^ | = note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1` - = note: but `A<'_, '2>` only implements `Foo` for some lifetime `'2` + = note: but `A<'_, '2>` only implements `Foo` for the lifetime `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index ee518b956ab1c..094c449802415 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -16,7 +16,7 @@ LL | want_hrtb::<&'a u32>() //~ ERROR | = note: Due to a where-clause on `want_hrtb`, = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `&'1 u32` only implements `Foo<&'1 isize>` for some lifetime `'1` + = note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 6469829e789b4..c1329d331a181 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -5,7 +5,7 @@ LL | <u32 as RefFoo<u32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'0 u32` must implement `Foo<'static, u32>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 @@ -14,7 +14,7 @@ LL | <i32 as RefFoo<i32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'0 i32` must implement `Foo<'static, i32>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 @@ -23,7 +23,7 @@ LL | <u64 as RefFoo<u64>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'0 u64` must implement `Foo<'static, u64>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 @@ -32,7 +32,7 @@ LL | <i64 as RefFoo<i64>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'0 i64` must implement `Foo<'static, i64>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for some lifetime `'1` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` error: aborting due to 4 previous errors diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 06f3659a5c17d..afc80bf4d8ee6 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -6,7 +6,7 @@ LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough | = note: Due to a where-clause on `foo`, = note: `&'0 _` must implement `Bar` for any lifetime `'0` - = note: but `&'1 u32` only implements `Bar` for some lifetime `'1` + = note: but `&'1 u32` only implements `Bar` for the lifetime `'1` error: aborting due to previous error From e9ba964f71f6917c39c8c110f491756c0645ebbb Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 19 Nov 2018 10:26:04 -0500 Subject: [PATCH 115/124] improve handling for subtype Still not great, but good enough to land this PR. --- src/librustc/infer/error_reporting/mod.rs | 47 ++++++-- .../nice_region_error/placeholder_error.rs | 110 ++++++++++-------- src/librustc/infer/error_reporting/note.rs | 20 ++++ src/librustc/infer/mod.rs | 2 +- src/librustc/ty/error.rs | 20 +--- src/librustc/ty/structural_impls.rs | 10 +- src/librustc/ty/sty.rs | 7 ++ .../higher-ranked-projection.bad.stderr | 22 +--- .../higher-ranked-projection.good.stderr | 2 +- .../higher-ranked-projection.rs | 2 +- .../expect-fn-supply-fn.rs | 2 +- .../expect-fn-supply-fn.stderr | 42 ++----- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 13 +-- .../hr-subtype.bound_a_vs_free_x.stderr | 12 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 13 +-- src/test/ui/hrtb/hrtb-exists-forall-fn.rs | 2 +- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 24 +--- ...igher-ranker-supertraits-transitive.stderr | 4 +- .../ui/hrtb/hrtb-higher-ranker-supertraits.rs | 2 - .../hrtb-higher-ranker-supertraits.stderr | 50 +------- src/test/ui/hrtb/hrtb-perfect-forwarding.rs | 2 +- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 22 +--- src/test/ui/issues/issue-40000.rs | 2 +- src/test/ui/issues/issue-40000.stderr | 26 +---- src/test/ui/lub-glb/old-lub-glb-object.rs | 2 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 15 +-- .../closure-arg-type-mismatch.rs | 2 - .../closure-arg-type-mismatch.stderr | 48 +------- .../ui/mismatched_types/closure-mismatch.rs | 2 +- .../mismatched_types/closure-mismatch.stderr | 15 +-- ...ons-fn-subtyping-return-static-fail.stderr | 13 +-- ...ion-lifetime-bounds-on-fns-where-clause.rs | 2 +- ...lifetime-bounds-on-fns-where-clause.stderr | 17 ++- ...ple-lifetime-bounds-on-fns-where-clause.rs | 2 +- ...lifetime-bounds-on-fns-where-clause.stderr | 17 ++- .../regions/regions-lifetime-bounds-on-fns.rs | 2 +- .../regions-lifetime-bounds-on-fns.stderr | 17 ++- 37 files changed, 233 insertions(+), 379 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d0cb718f55a25..4cce8343c02c8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -132,12 +132,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ReEmpty => ("the empty lifetime".to_owned(), None), + ty::RePlaceholder(_) => (format!("any other region"), None), + // FIXME(#13998) RePlaceholder should probably print like // ReFree rather than dumping Debug output on the user. // // We shouldn't really be having unification failures with ReVar // and ReLateBound though. - ty::RePlaceholder(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } @@ -324,8 +326,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the error. If all of these fails, we fall back to a rather // general bit of code that displays the error information RegionResolutionError::ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(region_scope_tree, origin, sub, sup) - .emit(); + if sub.is_placeholder() || sup.is_placeholder() { + self.report_placeholder_failure(region_scope_tree, origin, sub, sup) + .emit(); + } else { + self.report_concrete_failure(region_scope_tree, origin, sub, sup) + .emit(); + } } RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => { @@ -346,14 +353,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sup_origin, sup_r, ) => { - self.report_sub_sup_conflict( - region_scope_tree, - var_origin, - sub_origin, - sub_r, - sup_origin, - sup_r, - ); + if sub_r.is_placeholder() { + self.report_placeholder_failure( + region_scope_tree, + sub_origin, + sub_r, + sup_r, + ) + .emit(); + } else if sup_r.is_placeholder() { + self.report_placeholder_failure( + region_scope_tree, + sup_origin, + sub_r, + sup_r, + ) + .emit(); + } else { + self.report_sub_sup_conflict( + region_scope_tree, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ); + } } } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 07a61eb6d776e..0dda636a9bd53 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -14,9 +14,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit an descriptive diagnostic error. pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> { - // Check for the first case: relating two trait-refs, and we - // find a conflict between two placeholders. match &self.error { + /////////////////////////////////////////////////////////////////////////// + // NB. The ordering of cases in this match is very + // sensitive, because we are often matching against + // specific cases and then using an `_` to match all + // others. + + /////////////////////////////////////////////////////////////////////////// + // Check for errors from comparing trait failures -- first + // with two placeholders, then with one. Some(RegionResolutionError::SubSupConflict( vid, _, @@ -27,8 +34,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, sup_placeholder @ ty::RePlaceholder(_), - )) => if expected.def_id == found.def_id { - return Some(self.try_report_placeholders_trait( + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), @@ -36,10 +45,8 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected.def_id, expected.substs, found.substs, - )); - } else { - // I actually can't see why this would be the case ever. - }, + )) + } Some(RegionResolutionError::SubSupConflict( vid, @@ -51,8 +58,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, _, - )) => if expected.def_id == found.def_id { - return Some(self.try_report_placeholders_trait( + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), @@ -60,10 +69,8 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected.def_id, expected.substs, found.substs, - )); - } else { - // I actually can't see why this would be the case ever. - }, + )) + } Some(RegionResolutionError::SubSupConflict( vid, @@ -75,8 +82,10 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { _, _, sup_placeholder @ ty::RePlaceholder(_), - )) => if expected.def_id == found.def_id { - return Some(self.try_report_placeholders_trait( + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( Some(self.tcx.mk_region(ty::ReVar(*vid))), cause, None, @@ -84,17 +93,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected.def_id, expected.substs, found.substs, - )); - } else { - // I actually can't see why this would be the case ever. - }, - - Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(TypeTrace { .. }), - ty::RePlaceholder(_), - ty::RePlaceholder(_), - )) => { - // I actually can't see why this would be the case ever. + )) } Some(RegionResolutionError::ConcreteFailure( @@ -102,21 +101,21 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { cause, values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), - sub_region, + sub_region @ ty::RePlaceholder(_), sup_region @ ty::RePlaceholder(_), - )) => if expected.def_id == found.def_id { - return Some(self.try_report_placeholders_trait( - Some(sub_region), - cause, + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( None, + cause, + Some(*sub_region), Some(*sup_region), expected.def_id, expected.substs, found.substs, - )); - } else { - // I actually can't see why this would be the case ever. - }, + )) + } Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { @@ -125,24 +124,43 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }), sub_region @ ty::RePlaceholder(_), sup_region, - )) => if expected.def_id == found.def_id { - return Some(self.try_report_placeholders_trait( + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( Some(sup_region), cause, - None, Some(*sub_region), + None, expected.def_id, expected.substs, found.substs, - )); - } else { - // I actually can't see why this would be the case ever. - }, + )) + } - _ => {} - } + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region, + sup_region @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(sub_region), + cause, + None, + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )) + } - None + _ => None, + } } // error[E0308]: implementation of `Foo` does not apply to enough lifetimes diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 91da3197d3c1f..e45a4b17cdd9c 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -442,4 +442,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } } + + pub(super) fn report_placeholder_failure( + &self, + region_scope_tree: ®ion::ScopeTree, + placeholder_origin: SubregionOrigin<'tcx>, + sub: Region<'tcx>, + sup: Region<'tcx>, + ) -> DiagnosticBuilder<'tcx> { + // I can't think how to do better than this right now. -nikomatsakis + match placeholder_origin { + infer::Subtype(trace) => { + let terr = TypeError::RegionsPlaceholderMismatch; + self.report_and_explain_type_error(trace, &terr) + } + + _ => { + self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup) + } + } + } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 3b9affa6ffb50..461e09819d97d 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -225,7 +225,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>; /// See `error_reporting` module for more details -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum ValuePairs<'tcx> { Types(ExpectedFound<Ty<'tcx>>), Regions(ExpectedFound<ty::Region<'tcx>>), diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 6b931e39a05da..76e102d88d7ce 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -1,5 +1,5 @@ use hir::def_id::DefId; -use ty::{self, BoundRegion, Region, Ty, TyCtxt}; +use ty::{self, Region, Ty, TyCtxt}; use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; @@ -9,7 +9,7 @@ use syntax_pos::Span; use hir; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ExpectedFound<T> { pub expected: T, pub found: T, @@ -27,8 +27,7 @@ pub enum TypeError<'tcx> { ArgCount, RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), - RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), - RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), + RegionsPlaceholderMismatch, Sorts(ExpectedFound<Ty<'tcx>>), IntMismatch(ExpectedFound<ty::IntVarValue>), @@ -102,17 +101,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsDoesNotOutlive(..) => { write!(f, "lifetime mismatch") } - RegionsInsufficientlyPolymorphic(br, _) => { - write!(f, - "expected bound lifetime parameter{}{}, found concrete lifetime", - if br.is_named() { " " } else { "" }, - br) - } - RegionsOverlyPolymorphic(br, _) => { - write!(f, - "expected concrete lifetime, found bound lifetime parameter{}{}", - if br.is_named() { " " } else { "" }, - br) + RegionsPlaceholderMismatch => { + write!(f, "one type is more general than the other") } Sorts(values) => ty::tls::with(|tcx| { report_maybe_different(f, &values.expected.sort_string(tcx), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 4755adc4cd10d..f9b43f42d5298 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -434,12 +434,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsDoesNotOutlive(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)) } - RegionsInsufficientlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) - } - RegionsOverlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b)) - } + RegionsPlaceholderMismatch => RegionsPlaceholderMismatch, IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), Traits(x) => Traits(x), @@ -1006,8 +1001,7 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::FixedArraySize)(x), (ty::error::TypeError::ArgCount), (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), - (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), - (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), + (ty::error::TypeError::RegionsPlaceholderMismatch), (ty::error::TypeError::IntMismatch)(x), (ty::error::TypeError::FloatMismatch)(x), (ty::error::TypeError::Traits)(x), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f7adb83f8eb18..a2720bdf385cd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1396,6 +1396,13 @@ impl RegionKind { } } + pub fn is_placeholder(&self) -> bool { + match *self { + ty::RePlaceholder(..) => true, + _ => false, + } + } + pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool { match *self { ty::ReLateBound(debruijn, _) => debruijn >= index, diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index b5355e6009975..e4704494e1492 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,24 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ + | ^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:12), 'a) })... - = note: ...so that the types are compatible: - expected Mirror - found Mirror -note: but, the lifetime must be valid for the expression at 25:5... - --> $DIR/higher-ranked-projection.rs:25:5 - | -LL | foo(()); - | ^^^ -note: ...so type `fn(()) {foo::<&(), ()>}` of expression is valid during the expression - --> $DIR/higher-ranked-projection.rs:25:5 - | -LL | foo(()); - | ^^^ + = note: expected type `Mirror` + found type `Mirror` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index a837df0cd2429..db15ec51d87c6 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,7 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR E0495 +LL | | //[bad]~^ ERROR E0308 LL | | } | |_^ diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 2d2221c6c6392..5b380c982f041 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo<U, T>(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR E0495 + //[bad]~^ ERROR E0308 } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 49f6565540b7e..6977fd47a2e85 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -44,7 +44,7 @@ fn expect_bound_supply_free_from_closure() { // the argument level. type Foo<'a> = fn(&'a u32); with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - //~^ ERROR cannot infer + //~^ ERROR mismatched types }); } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index d140e9989a3f6..b1cfd6cef1022 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -40,57 +40,29 @@ error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:30:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^ lifetime mismatch + | ^^^^^^^^ one type is more general than the other | = note: expected type `fn(&u32)` found type `for<'r> fn(&'r u32)` - = note: lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) })... -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 30:48 - --> $DIR/expect-fn-supply-fn.rs:30:48 - | -LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:37:53 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^ one type is more general than the other | = note: expected type `for<'r> fn(&'r u32)` found type `fn(&'x u32)` - = note: lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 34:37 - --> $DIR/expect-fn-supply-fn.rs:34:37 - | -LL | fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { - | ^^ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements +error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:46:53 | LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^ - | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... - = note: ...so that the types are compatible: - expected for<'r> fn(&'r u32) - found fn(&u32) -note: but, the lifetime must be valid for the expression at 46:65... - --> $DIR/expect-fn-supply-fn.rs:46:65 + | ^^^^^^^ one type is more general than the other | -LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | _________________________________________________________________^ -LL | | //~^ ERROR cannot infer -LL | | }); - | |_____^ -note: ...so that the type `fn(&u32)` will meet its required lifetime bounds - --> $DIR/expect-fn-supply-fn.rs:46:53 - | -LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^ + = note: expected type `for<'r> fn(&'r u32)` + found type `fn(&u32)` error: aborting due to 5 previous errors -Some errors occurred: E0308, E0495. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index 4069e3b25ade0..bdfabdabbebb7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,19 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } | |_________________________________________________________________________________________- in this macro invocation | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:26), 'b) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:25), 'a) })... - = note: ...so that the expression is assignable: - expected std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32> - found std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32> + = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>` + found type `std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index bb1a828f3da4b..74b8c89b6e86f 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } @@ -10,16 +10,6 @@ LL | | fn(&'x u32)) } | = note: expected type `std::option::Option<for<'a> fn(&'a u32)>` found type `std::option::Option<fn(&'x u32)>` - = note: lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:23), 'a) })... -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 38:22 - --> $DIR/hr-subtype.rs:38:22 - | -LL | fn supertype<'x,'y:'x,'z:'y>() { - | ^^ -... -LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), -LL | | fn(&'x u32)) } - | |___________________________________________- in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 1a806bd2cb550..8168941e2777c 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,19 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | |__________________________________________________________________________- in this macro invocation | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:25), 'a) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:26), 'b) })... - = note: ...so that the expression is assignable: - expected std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)> - found std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)> + = note: expected type `std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>` + found type `std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs index bba1f4dfb86c2..24182d76b3581 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs @@ -19,5 +19,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer + let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 75ba89f58da1b..4a2a619298cd5 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -1,24 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:22:34 | -LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer - | ^^^ +LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types + | ^^^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'b) })... - = note: ...so that the expression is assignable: - expected for<'b> fn(&'b u32) - found fn(&u32) -note: but, the lifetime must be valid for the call at 22:34... - --> $DIR/hrtb-exists-forall-fn.rs:22:34 - | -LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer - | ^^^^^ -note: ...so type `fn(&u32)` of expression is valid during the expression - --> $DIR/hrtb-exists-forall-fn.rs:22:34 - | -LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer - | ^^^^^ + = note: expected type `for<'b> fn(&'b u32)` + found type `fn(&u32)` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index b02764184fbe9..0d7b5cbf82348 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -2,12 +2,10 @@ error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | LL | want_bar_for_any_ccx(b); //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected type `for<'ccx> Bar<'ccx>` found type `Bar<'static>` - = note: lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:16), 'ccx) })... - = note: ...does not necessarily outlive the static lifetime error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs index 638587f428d78..3d2d403462d8b 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs @@ -16,7 +16,6 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) { want_foo_for_some_tcx(f); want_foo_for_any_tcx(f); //~ ERROR E0308 - //~^ ERROR E0308 } fn want_foo_for_any_tcx<F>(f: &F) @@ -34,7 +33,6 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_bar_for_some_ccx(b); want_bar_for_any_ccx(b); //~ ERROR E0308 - //~^ ERROR E0308 } fn want_bar_for_any_ccx<B>(b: &B) diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index 71ed59ce2ff7e..31dbeec2a551b 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -2,62 +2,20 @@ error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | LL | want_foo_for_any_tcx(f); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected type `for<'tcx> Foo<'tcx>` found type `Foo<'x>` - = note: lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:15), 'tcx) })... -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 14:26 - --> $DIR/hrtb-higher-ranker-supertraits.rs:14:26 - | -LL | fn want_foo_for_some_tcx<'x,F>(f: &'x F) - | ^^ - -error[E0308]: mismatched types - --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 - | -LL | want_foo_for_any_tcx(f); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `for<'tcx> Foo<'tcx>` - found type `Foo<'x>` -note: the lifetime 'x as defined on the function body at 14:26... - --> $DIR/hrtb-higher-ranker-supertraits.rs:14:26 - | -LL | fn want_foo_for_some_tcx<'x,F>(f: &'x F) - | ^^ - = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U4, name: BrNamed(crate0:DefIndex(1:15), 'tcx) }) error[E0308]: mismatched types - --> $DIR/hrtb-higher-ranker-supertraits.rs:36:5 + --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 | LL | want_bar_for_any_ccx(b); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected type `for<'ccx> Bar<'ccx>` found type `Bar<'x>` - = note: lifetime RePlaceholder(Placeholder { universe: U8, name: BrNamed(crate0:DefIndex(1:19), 'ccx) })... -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 29:26 - --> $DIR/hrtb-higher-ranker-supertraits.rs:29:26 - | -LL | fn want_bar_for_some_ccx<'x,B>(b: &B) - | ^^ - -error[E0308]: mismatched types - --> $DIR/hrtb-higher-ranker-supertraits.rs:36:5 - | -LL | want_bar_for_any_ccx(b); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'x>` -note: the lifetime 'x as defined on the function body at 29:26... - --> $DIR/hrtb-higher-ranker-supertraits.rs:29:26 - | -LL | fn want_bar_for_some_ccx<'x,B>(b: &B) - | ^^ - = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U8, name: BrNamed(crate0:DefIndex(1:19), 'ccx) }) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 31dad39efc3f5..7bd89960e42e5 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs @@ -43,7 +43,7 @@ fn foo_hrtb_bar_not<'b,T>(mut t: T) // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // clause only specifies `T : Bar<&'b isize>`. - foo_hrtb_bar_not(&mut t); //~ ERROR E0495 + foo_hrtb_bar_not(&mut t); //~ ERROR E0308 } fn foo_hrtb_bar_hrtb<T>(mut t: T) diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 2de60a79a85bd..ec3bf8a1a1be3 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -1,22 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0308]: mismatched types --> $DIR/hrtb-perfect-forwarding.rs:46:5 | -LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0495 - | ^^^^^^^^^^^^^^^^ +LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrNamed(crate0:DefIndex(1:23), 'a) })... - = note: ...so that the types are compatible: - expected Foo<&'a isize> - found Foo<&isize> -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 39:21... - --> $DIR/hrtb-perfect-forwarding.rs:39:21 - | -LL | fn foo_hrtb_bar_not<'b,T>(mut t: T) - | ^^ - = note: ...so that the types are compatible: - expected Bar<&isize> - found Bar<&'b isize> + = note: expected type `Foo<&'a isize>` + found type `Foo<&isize>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-40000.rs b/src/test/ui/issues/issue-40000.rs index c7d1900ada958..320992c0764cf 100644 --- a/src/test/ui/issues/issue-40000.rs +++ b/src/test/ui/issues/issue-40000.rs @@ -3,5 +3,5 @@ fn main() { fn foo(x: Box<Fn(&i32)>) {} let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; - foo(bar); //~ ERROR E0495 + foo(bar); //~ ERROR E0308 } diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 3aa1da8680c02..d7966cea52bb0 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -1,26 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | -LL | foo(bar); //~ ERROR E0495 - | ^^^ +LL | foo(bar); //~ ERROR E0308 + | ^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U8, name: BrAnon(0) })... - = note: ...so that the types are compatible: - expected dyn for<'r> std::ops::Fn(&'r i32) - found dyn std::ops::Fn(&i32) -note: but, the lifetime must be valid for the block suffix following statement 2 at 5:5... - --> $DIR/issue-40000.rs:5:5 - | -LL | / let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; -LL | | foo(bar); //~ ERROR E0495 -LL | | } - | |_^ -note: ...so that variable is valid at time of its declaration - --> $DIR/issue-40000.rs:5:9 - | -LL | let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; - | ^^^ + = note: expected type `dyn for<'r> std::ops::Fn(&'r i32)` + found type `dyn std::ops::Fn(&i32)` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 132df608af71a..9be7a813603d4 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -7,7 +7,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { //~ ERROR cannot infer + let z = match 22 { //~ ERROR E0308 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 2ed180f25dc02..17d3648156b51 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,19 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error[E0308]: mismatched types --> $DIR/old-lub-glb-object.rs:10:13 | -LL | let z = match 22 { //~ ERROR cannot infer +LL | let z = match 22 { //~ ERROR E0308 | _____________^ LL | | 0 => x, LL | | _ => y, LL | | }; - | |_____^ + | |_____^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U5, name: BrNamed(crate0:DefIndex(1:11), 'a) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U5, name: BrNamed(crate0:DefIndex(1:12), 'b) })... - = note: ...so that the types are compatible: - expected dyn for<'a, 'b> Foo<&'a u8, &'b u8> - found dyn for<'a> Foo<&'a u8, &'a u8> + = note: expected type `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found type `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index f71a1736d4d3f..437150666be0c 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -9,6 +9,4 @@ fn baz<F: Fn(*mut &u32)>(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); //~ ERROR mismatched types //~| ERROR mismatched types - //~| ERROR mismatched types - //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 2cd63099bb756..a6628006587c1 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -26,63 +26,21 @@ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); //~ ERROR mismatched types - | ^^^ lifetime mismatch + | ^^^ one type is more general than the other | = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` found type `std::ops::Fn<(*mut &'a u32,)>` - = note: lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) })... -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 9:10 - --> $DIR/closure-arg-type-mismatch.rs:9:10 - | -LL | fn _test<'a>(f: fn(*mut &'a u32)) { - | ^^ - -error[E0308]: mismatched types - --> $DIR/closure-arg-type-mismatch.rs:10:5 - | -LL | baz(f); //~ ERROR mismatched types - | ^^^ lifetime mismatch - | - = note: expected type `std::ops::FnOnce<(*mut &u32,)>` - found type `std::ops::FnOnce<(*mut &'a u32,)>` - = note: lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) })... -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 9:10 - --> $DIR/closure-arg-type-mismatch.rs:9:10 - | -LL | fn _test<'a>(f: fn(*mut &'a u32)) { - | ^^ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); //~ ERROR mismatched types - | ^^^ lifetime mismatch - | - = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` - found type `std::ops::Fn<(*mut &'a u32,)>` -note: the lifetime 'a as defined on the function body at 9:10... - --> $DIR/closure-arg-type-mismatch.rs:9:10 - | -LL | fn _test<'a>(f: fn(*mut &'a u32)) { - | ^^ - = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U2, name: BrAnon(0) }) - -error[E0308]: mismatched types - --> $DIR/closure-arg-type-mismatch.rs:10:5 - | -LL | baz(f); //~ ERROR mismatched types - | ^^^ lifetime mismatch + | ^^^ one type is more general than the other | = note: expected type `std::ops::FnOnce<(*mut &u32,)>` found type `std::ops::FnOnce<(*mut &'a u32,)>` -note: the lifetime 'a as defined on the function body at 9:10... - --> $DIR/closure-arg-type-mismatch.rs:9:10 - | -LL | fn _test<'a>(f: fn(*mut &'a u32)) { - | ^^ - = note: ...does not necessarily outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrAnon(0) }) -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0308, E0631. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 0f28e5dfd7ee0..152a525493732 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,5 +5,5 @@ impl<T: Fn(&())> Foo for T {} fn baz<T: Foo>(_: T) {} fn main() { - baz(|_| ()); //~ ERROR E0495 + baz(|_| ()); //~ ERROR E0308 } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index f028817a935a7..0d87bc228755f 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,15 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | baz(|_| ()); //~ ERROR E0495 - | ^^^ +LL | baz(|_| ()); //~ ERROR E0308 + | ^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U6, name: BrAnon(0) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U6, name: BrAnon(0) })... - = note: ...so that the types are compatible: - expected for<'r> std::ops::Fn<(&'r (),)> - found std::ops::Fn<(&(),)> + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index c9ccb9b6ded3d..a9234e43191ea 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,15 +1,12 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements +error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); //~ ERROR - | ^^^ + | ^^^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'cx) })... - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the expression is assignable: - expected for<'cx> fn(&'cx S) -> &'static S - found for<'r> fn(&'r S) -> &'r S + = note: expected type `for<'cx> fn(&'cx S) -> &'static S` + found type `for<'r> fn(&'r S) -> &'r S` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs index e5514d32c4e9f..ab4c6d9cf9198 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -17,7 +17,7 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 + let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types } fn e() { diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 3824755fa06f5..47e1d0efdc77b 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -16,19 +16,16 @@ LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | a(x, y); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | -LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 - | ^ +LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types + | ^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...so that the expression is assignable: - expected for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize) - found for<'r, 's> fn(&'r mut &isize, &'s mut &isize) + = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors -Some errors occurred: E0495, E0623. -For more information about an error, try `rustc --explain E0495`. +Some errors occurred: E0308, E0623. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 3e635300d7b68..066522548ad45 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -19,7 +19,7 @@ fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0495 + let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 } fn e() { diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index f694d31264070..1e7b99053f77f 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -27,19 +27,16 @@ LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | a(x, y, z); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | -LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0495 - | ^ +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 + | ^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...so that the expression is assignable: - expected for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize) - found for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) + = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` + found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors -Some errors occurred: E0495, E0623. -For more information about an error, try `rustc --explain E0495`. +Some errors occurred: E0308, E0623. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs index 6ebfc3f80d252..7d7f62e19792f 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -17,7 +17,7 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 + let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 } fn e() { diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index 20e28e8877fca..a43ee7ec3ace0 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -16,19 +16,16 @@ LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | a(x, y); //~ ERROR lifetime mismatch [E0623] | ^ ...but data from `y` flows into `x` here -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | -LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0495 - | ^ +LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 + | ^ one type is more general than the other | - = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U1, name: BrAnon(1) })... - = note: ...so that the expression is assignable: - expected for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize) - found for<'r, 's> fn(&'r mut &isize, &'s mut &isize) + = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors -Some errors occurred: E0495, E0623. -For more information about an error, try `rustc --explain E0495`. +Some errors occurred: E0308, E0623. +For more information about an error, try `rustc --explain E0308`. From 6d6f12efd935dff117a97bdd2d5b7c9953560640 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 19 Nov 2018 10:29:50 -0500 Subject: [PATCH 116/124] pacify the mercilous tidy --- src/librustc/util/ppaux.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 0742d0aebe954..79405b124001d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -90,7 +90,11 @@ impl RegionHighlightMode { /// During the execution of `op`, highlight the region inference /// vairable `vid` as `'N`. We can only highlight one region vid /// at a time. - pub fn highlighting_region<R>(region: ty::Region<'_>, number: usize, op: impl FnOnce() -> R) -> R { + pub fn highlighting_region<R>( + region: ty::Region<'_>, + number: usize, + op: impl FnOnce() -> R, + ) -> R { let old_mode = Self::get(); let mut new_mode = old_mode; let first_avail_slot = new_mode.highlight_regions.iter_mut() @@ -1076,12 +1080,10 @@ impl fmt::Debug for ty::FloatVid { impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if RegionHighlightMode::get().any_region_vids_highlighted() { - if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) { - return write!(f, "'{:?}", counter); - } else { - return write!(f, "'_"); - } + if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) { + return write!(f, "'{:?}", counter); + } else if RegionHighlightMode::get().any_region_vids_highlighted() { + return write!(f, "'_"); } write!(f, "'_#{}r", self.index()) From 57f76be0310742273e1d7656e1e4d1846fb65e04 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 19 Nov 2018 10:47:34 -0500 Subject: [PATCH 117/124] address tmandry nits --- src/test/ui/coherence/coherence-subtyping.rs | 32 ++----------------- .../ui/coherence/coherence-subtyping.stderr | 30 ++++------------- src/test/ui/hrtb/hrtb-exists-forall-fn.rs | 13 +++----- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 2 +- 4 files changed, 14 insertions(+), 63 deletions(-) diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs index 2ac9156017829..fb9a7fbf7aba5 100644 --- a/src/test/ui/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -1,40 +1,14 @@ // Test that two distinct impls which match subtypes of one another // yield coherence errors (or not) depending on the variance. -trait Contravariant { +trait TheTrait { fn foo(&self) { } } -impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { +impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } -impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //~^ ERROR -} - -/////////////////////////////////////////////////////////////////////////// - -trait Covariant { - fn foo(&self) { } -} - -impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { -} - -impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //~^ ERROR -} - -/////////////////////////////////////////////////////////////////////////// - -trait Invariant { - fn foo(&self) { } -} - -impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { -} - -impl Invariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { +impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { //~^ ERROR } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index eb68768eed072..1f9b2cb6fdfa3 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -1,30 +1,12 @@ -error[E0119]: conflicting implementations of trait `Contravariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: +error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: --> $DIR/coherence-subtyping.rs:11:1 | -LL | impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | -------------------------------------------------------------- first implementation here +LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { + | --------------------------------------------------------- first implementation here ... -LL | impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` +LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` -error[E0119]: conflicting implementations of trait `Covariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:24:1 - | -LL | impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | ---------------------------------------------------------- first implementation here -... -LL | impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - -error[E0119]: conflicting implementations of trait `Invariant` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:37:1 - | -LL | impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | ---------------------------------------------------------- first implementation here -... -LL | impl Invariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - -error: aborting due to 3 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs index 24182d76b3581..828331cb950ed 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs @@ -3,21 +3,16 @@ // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -trait Trait<T> {} - fn foo<'a>() -> fn(&'a u32) { panic!() } fn main() { - // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // Here, proving that `fn(&'a u32) <: for<'b> fn(&'b u32)`: // - // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` - // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` - // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` - // - This requires (among other things) instantiating `'b` universally, - // yielding `fn(&!b u32)`, in a fresh universe U1 - // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. + // - instantiates `'b` with a placeholder `!b`, + // - requires that `&!b u32 <: &'a u32` and hence that `!b: 'a`, + // - but we can never know this. let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 4a2a619298cd5..6301ed45ac277 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/hrtb-exists-forall-fn.rs:22:34 + --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types | ^^^^^ one type is more general than the other From a90bd6ce96bbc19affee39f914d4dc42a2f0f92e Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 19 Nov 2018 10:56:24 -0500 Subject: [PATCH 118/124] add some comments about lifetimes etc --- src/librustc/ty/util.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0fa4c98be6370..e50095c94d76b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -621,6 +621,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'tcx> ty::TyS<'tcx> { + /// Checks whether values of this type `T` are *moved* or *copied* + /// when referenced -- this amounts to a check for whether `T: + /// Copy`, but note that we **don't** consider lifetimes when + /// doing this check. This means that we may generate MIR which + /// does copies even when the type actually doesn't satisfy the + /// full requirements for the `Copy` trait (cc #29149) -- this + /// winds up being reported as an error during NLL borrow check. pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -629,6 +636,12 @@ impl<'a, 'tcx> ty::TyS<'tcx> { !tcx.at(span).is_copy_raw(param_env.and(self)) } + /// Checks whether values of this type `T` have a size known at + /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored + /// for the purposes of this check, so it can be an + /// over-approximation in generic contexts, where one can have + /// strange rules like `<T as Foo<'static>>::Bar: Sized` that + /// actually carry lifetime requirements. pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>)-> bool @@ -636,6 +649,11 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tcx_at.is_sized_raw(param_env.and(self)) } + /// Checks whether values of this type `T` implement the `Freeze` + /// trait -- frozen types are those that do not contain a + /// `UnsafeCell` anywhere. This is a language concept used to + /// determine how to handle `static` values, the trait itself is + /// not exposed to end users. pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, From 500c0933633cf350038fc6cac10a18345f0d6ac8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Mon, 19 Nov 2018 11:57:22 -0500 Subject: [PATCH 119/124] pacify the mercilous eddyb ;) --- src/librustc/ty/util.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index e50095c94d76b..c98c575fce28c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -652,8 +652,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> { /// Checks whether values of this type `T` implement the `Freeze` /// trait -- frozen types are those that do not contain a /// `UnsafeCell` anywhere. This is a language concept used to - /// determine how to handle `static` values, the trait itself is - /// not exposed to end users. + /// distinguish "true immutability", which is relevant to + /// optimization as well as the rules around static values. Note + /// that the `Freeze` trait is not exposed to end users and is + /// effectively an implementation detail. pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, From 0c81a2ff22f0ddcd8beb865c8424f3243c735475 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 20 Nov 2018 10:24:38 -0500 Subject: [PATCH 120/124] track if any region constraints involved placeholders --- src/librustc/infer/mod.rs | 7 ++++- src/librustc/infer/region_constraints/mod.rs | 33 ++++++++++++++------ src/librustc/traits/select.rs | 7 ++--- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 461e09819d97d..0a5e399aaad75 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -867,10 +867,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r } + /// Scan the constraints produced since `snapshot` began and returns: + /// + /// - None -- if none of them involve "region outlives" constraints + /// - Some(true) -- if there are `'a: 'b` constraints where `'a` or `'b` is a placehodler + /// - Some(false) -- if there are `'a: 'b` constraints but none involve placeholders pub fn region_constraints_added_in_snapshot( &self, snapshot: &CombinedSnapshot<'a, 'tcx>, - ) -> bool { + ) -> Option<bool> { self.borrow_region_constraints().region_constraints_added_in_snapshot( &snapshot.region_constraints_snapshot, ) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index b29eb67dfa225..56ae850226c91 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -128,6 +128,16 @@ pub enum Constraint<'tcx> { RegSubReg(Region<'tcx>, Region<'tcx>), } +impl Constraint<'_> { + pub fn involves_placeholders(&self) -> bool { + match self { + Constraint::VarSubVar(_, _) => false, + Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(), + Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(), + } + } +} + /// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or /// associated type) must outlive the region `R`. `T` is known to /// outlive `RS`. Therefore verify that `R <= RS[i]` for some @@ -324,6 +334,8 @@ impl TaintDirections { } } +pub struct ConstraintInfo {} + impl<'tcx> RegionConstraintCollector<'tcx> { pub fn new() -> Self { Self::default() @@ -485,7 +497,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); - let u_vid = self.unification_table + let u_vid = self + .unification_table .new_key(unify_key::RegionVidKey { min_vid: vid }); assert_eq!(vid, u_vid); if self.in_snapshot() { @@ -517,7 +530,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); - let constraints_to_kill: Vec<usize> = self.undo_log + let constraints_to_kill: Vec<usize> = self + .undo_log .iter() .enumerate() .rev() @@ -820,17 +834,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> { .filter_map(|&elt| match elt { AddVar(vid) => Some(vid), _ => None, - }) - .collect() + }).collect() } - pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> bool { + /// See [`RegionInference::region_constraints_added_in_snapshot`] + pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> Option<bool> { self.undo_log[mark.length..] .iter() - .any(|&elt| match elt { - AddConstraint(_) => true, - _ => false, - }) + .map(|&elt| match elt { + AddConstraint(constraint) => Some(constraint.involves_placeholders()), + _ => None, + }).max() + .unwrap_or(None) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index f5e96286d184e..373ec2d5e490f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -639,10 +639,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) -> Result<EvaluationResult, OverflowError> { self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> { let result = op(self)?; - if !self.infcx.region_constraints_added_in_snapshot(snapshot) { - Ok(result) - } else { - Ok(result.max(EvaluatedToOkModuloRegions)) + match self.infcx.region_constraints_added_in_snapshot(snapshot) { + None => Ok(result), + Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), } }) } From f17caab0e7f7144f29f6de75ce04bbf7aed4687d Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 20 Nov 2018 11:20:05 -0500 Subject: [PATCH 121/124] try to detect affected code and direct people to #56105 --- src/librustc/traits/coherence.rs | 39 ++++++++++++++++--- src/librustc/traits/mod.rs | 3 +- src/librustc/traits/specialize/mod.rs | 6 +++ .../traits/specialize/specialization_graph.rs | 1 + .../coherence/inherent_impls_overlap.rs | 4 ++ .../ui/coherence/coherence-subtyping.stderr | 2 + 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 980c98d2a2d50..b3d732ebcd7dc 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -4,6 +4,7 @@ //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html +use infer::CombinedSnapshot; use hir::def_id::{DefId, LOCAL_CRATE}; use syntax_pos::DUMMY_SP; use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; @@ -33,6 +34,17 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, + + /// True if the overlap might've been permitted before the shift + /// to universes. + pub involves_placeholder: bool, +} + +pub fn add_placeholder_note(err: &mut ::errors::DiagnosticBuilder<'_>) { + err.note(&format!( + "this behavior recently changed as a result of a bug fix; \ + see rust-lang/rust#56105 for details" + )); } /// If there are types that satisfy both impls, invokes `on_overlap` @@ -104,13 +116,22 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, ' /// Can both impl `a` and impl `b` be satisfied by a common type (including /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls. -fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, - a_def_id: DefId, - b_def_id: DefId) - -> Option<OverlapResult<'tcx>> -{ +fn overlap<'cx, 'gcx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, +) -> Option<OverlapResult<'tcx>> { debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); + selcx.infcx().probe(|snapshot| overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)) +} + +fn overlap_within_probe( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, + snapshot: &CombinedSnapshot<'_, 'tcx>, +) -> Option<OverlapResult<'tcx>> { // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with // fresh type variables, and hence we do our evaluations in an @@ -158,7 +179,13 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); - Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) + + let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) { + Some(true) => true, + _ => false, + }; + + Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 0377b98d3f863..b42d742b7f841 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -43,7 +43,8 @@ pub use self::FulfillmentErrorCode::*; pub use self::Vtable::*; pub use self::ObligationCauseCode::*; -pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; +pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; +pub use self::coherence::{OrphanCheckErr, OverlapResult}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::project::MismatchedProjectionTypes; pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f5d68ddb5bd46..63f52a34dfa70 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -15,6 +15,7 @@ use hir::def_id::DefId; use infer::{InferCtxt, InferOk}; use lint; use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; +use traits::coherence; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax_pos::DUMMY_SP; @@ -32,6 +33,7 @@ pub struct OverlapError { pub trait_desc: String, pub self_desc: Option<String>, pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, + pub involves_placeholder: bool, } /// Given a subst for the requested impl, translate it to a subst @@ -370,6 +372,10 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit(); } } else { diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index fd68917e53991..db3547b2b7479 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> Children { None }, intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, + involves_placeholder: overlap.involves_placeholder, } }; diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index e568320ba8e73..8d27a77b29c6c 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -73,6 +73,10 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + traits::add_placeholder_note(&mut err); + } + err.emit(); } } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index 1f9b2cb6fdfa3..b29a918f2d982 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -6,6 +6,8 @@ LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { ... LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + | + = note: this behavior recently changed as a result of a bug fix; see #XXX for details error: aborting due to previous error From 96640adac9fc74add2a1d7ca1ad6e8af07bb5cdf Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 20 Nov 2018 11:59:06 -0500 Subject: [PATCH 122/124] rename `type_moves_by_default` to `type_is_copy_modulo_regions` --- src/librustc/infer/mod.rs | 7 ++++--- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/mem_categorization.rs | 15 ++++++++------- src/librustc/ty/query/mod.rs | 2 +- src/librustc/ty/util.rs | 18 +++++++++--------- src/librustc_lint/builtin.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 18 +++++++++++------- src/librustc_mir/build/misc.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 4 ++-- src/librustc_mir/hair/pattern/check_match.rs | 2 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/check_unsafety.rs | 7 +++++-- src/librustc_typeck/check/demand.rs | 6 +++--- src/librustc_typeck/check/op.rs | 12 ++++++------ .../ui/coherence/coherence-subtyping.stderr | 2 +- 15 files changed, 55 insertions(+), 46 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 0a5e399aaad75..2d3fb137fafdd 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1400,18 +1400,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .verify_generic_bound(origin, kind, a, bound); } - pub fn type_moves_by_default( + pub fn type_is_copy_modulo_regions( &self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, span: Span, ) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); + // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. if !self.in_progress_tables.is_some() || !ty.has_closure_types() { if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { - return ty.moves_by_default(self.tcx.global_tcx(), param_env, span); + return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span); } } @@ -1421,7 +1422,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - !traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) } /// Obtains the latest type of the given closure; this may be a diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f9bcbb3222955..c1aa25b6b75c2 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -976,7 +976,7 @@ fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx move_reason: MoveReason) -> ConsumeMode { - if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) { + if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) { Move(move_reason) } else { Copy diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 207382d5e1f45..370f0d1a6c6d7 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -443,15 +443,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - pub fn type_moves_by_default(&self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span) - -> bool { - self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span)) + pub fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool { + self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span)) .or_else(|| { self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { - ty.moves_by_default(self.tcx.global_tcx(), param_env, span) + ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span) }) }) .unwrap_or(true) diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 842aea07614dd..4d026b97233ee 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -382,7 +382,7 @@ define_queries! { <'tcx> /// might want to use `reveal_all()` method to change modes. [] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>, - /// Trait selection queries. These are best used by invoking `ty.moves_by_default()`, + /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. [] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index c98c575fce28c..ac062a2378611 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -203,7 +203,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { let cause = ObligationCause { span, ..ObligationCause::dummy() }; let ctx = traits::FulfillmentContext::new(); match traits::fully_normalize(&infcx, ctx, cause, self, &ty) { - Ok(ty) => if infcx.type_moves_by_default(self, ty, span) { + Ok(ty) => if !infcx.type_is_copy_modulo_regions(self, ty, span) { infringing.push(field); } Err(errors) => { @@ -628,12 +628,12 @@ impl<'a, 'tcx> ty::TyS<'tcx> { /// does copies even when the type actually doesn't satisfy the /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. - pub fn moves_by_default(&'tcx self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - span: Span) - -> bool { - !tcx.at(span).is_copy_raw(param_env.and(self)) + pub fn is_copy_modulo_regions(&'tcx self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + span: Span) + -> bool { + tcx.at(span).is_copy_raw(param_env.and(self)) } /// Checks whether values of this type `T` have a size known at @@ -947,11 +947,11 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `ManuallyDrop` doesn't have a destructor regardless of field types. ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false, - // Issue #22536: We first query type_moves_by_default. It sees a + // Issue #22536: We first query `is_copy_modulo_regions`. It sees a // normalized version of the type, and therefore will definitely // know whether the type implements Copy (and thus needs no // cleanup/drop/zeroing) ... - _ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false, + _ if ty.is_copy_modulo_regions(tcx, param_env, DUMMY_SP) => false, // ... (issue #22536 continued) but as an optimization, still use // prior logic of asking for the structural "may drop". diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index cd4cbcc13a6f2..27b65b4ec48a4 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -540,7 +540,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { return; } let param_env = ty::ParamEnv::empty(); - if !ty.moves_by_default(cx.tcx, param_env, item.span) { + if ty.is_copy_modulo_regions(cx.tcx, param_env, item.span) { return; } if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 8bb67521f4431..b3e1237a45087 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -503,13 +503,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]), }; - // In order to have a Copy operand, the type T of the value must be Copy. Note that we - // prove that T: Copy, rather than using the type_moves_by_default test. This is - // important because type_moves_by_default ignores the resulting region obligations and - // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored - // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds - // fully apply: in effect, the rule is that if a value of some type could implement - // Copy, then it must. + // In order to have a Copy operand, the type T of the + // value must be Copy. Note that we prove that T: Copy, + // rather than using the `is_copy_modulo_regions` + // test. This is important because + // `is_copy_modulo_regions` ignores the resulting region + // obligations and assumes they pass. This can result in + // bounds from Copy impls being unsoundly ignored (e.g., + // #29149). Note that we decide to use Copy before knowing + // whether the bounds fully apply: in effect, the rule is + // that if a value of some type could implement Copy, then + // it must. self.cx.prove_trait_ref( trait_ref, location.to_locations(), diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 472f05a101f9e..5b20d412f0dd5 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { let tcx = self.hir.tcx(); let ty = place.ty(&self.local_decls, tcx).to_ty(tcx); - if self.hir.type_moves_by_default(ty, DUMMY_SP) { + if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) { Operand::Move(place) } else { Operand::Copy(place) diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 60c8022a374be..07f3c38c62c52 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -223,8 +223,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.check_overflow } - pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { - self.infcx.type_moves_by_default(self.param_env, ty, span) + pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { + self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) } } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index f758e48887715..c104af7a7d81b 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -545,7 +545,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, match bm { ty::BindByValue(..) => { let pat_ty = cx.tables.node_id_to_type(p.hir_id); - if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { + if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p), span_vec); } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 4c123d4a44b05..2aa44cc181a56 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -310,7 +310,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("build_clone_shim(def_id={:?})", def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span); + let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span); let dest = Place::Local(RETURN_PLACE); let src = Place::Local(Local::new(1+0)).deref(); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 0b0845ef945d0..eb151b56bed65 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -224,8 +224,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { "non-field projection {:?} from union?", place) }; - if elem_ty.moves_by_default(self.tcx, self.param_env, - self.source_info.span) { + if !elem_ty.is_copy_modulo_regions( + self.tcx, + self.param_env, + self.source_info.span, + ) { self.require_unsafe( "assignment to non-`Copy` union field", "the previous content of the field will be dropped, which \ diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 84ca77663a6ab..7a788f2de7f2f 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -353,9 +353,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Maybe add `*`? Only if `T: Copy`. _ => { - if !self.infcx.type_moves_by_default(self.param_env, - checked, - sp) { + if self.infcx.type_is_copy_modulo_regions(self.param_env, + checked, + sp) { // do not suggest if the span comes from a macro (#52783) if let (Ok(code), true) = (cm.span_to_snippet(sp), sp == expr.span) { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 8cf97970a1556..7c871601af308 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -262,9 +262,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { - !self.infcx.type_moves_by_default(self.param_env, - rty, - lhs_expr.span) && + self.infcx.type_is_copy_modulo_regions(self.param_env, + rty, + lhs_expr.span) && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)) @@ -334,9 +334,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { - !self.infcx.type_moves_by_default(self.param_env, - rty, - lhs_expr.span) && + self.infcx.type_is_copy_modulo_regions(self.param_env, + rty, + lhs_expr.span) && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)) diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index b29a918f2d982..1fc5c39d5c9fd 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -7,7 +7,7 @@ LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` | - = note: this behavior recently changed as a result of a bug fix; see #XXX for details + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error: aborting due to previous error From 0303de648a7b474c2526024210f34a7f25084ae6 Mon Sep 17 00:00:00 2001 From: John Heitmann <jheitmann@gmail.com> Date: Fri, 4 Jan 2019 23:15:59 -0800 Subject: [PATCH 123/124] Add optional eslint to the rustdoc-js test target --- config.toml.example | 4 ++++ src/bootstrap/config.rs | 3 +++ src/bootstrap/test.rs | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/config.toml.example b/config.toml.example index f75e220de47e7..236d18dda8eb0 100644 --- a/config.toml.example +++ b/config.toml.example @@ -144,6 +144,10 @@ # target when running tests, otherwise this can be omitted. #nodejs = "node" +# The eslint executable to use. Note that this is only used for linting js files +# during the test phase. It can be omitted. +#eslint = "eslint" + # Python interpreter to use for various tasks throughout the build, notably # rustdoc tests, the lldb python interpreter, and some dist bits and pieces. # Note that Python 2 is currently required. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8655cf0eb3053..872cd200266eb 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -136,6 +136,7 @@ pub struct Config { pub libdir: Option<PathBuf>, pub mandir: Option<PathBuf>, pub codegen_tests: bool, + pub eslint: Option<PathBuf>, pub nodejs: Option<PathBuf>, pub gdb: Option<PathBuf>, pub python: Option<PathBuf>, @@ -202,6 +203,7 @@ struct Build { gdb: Option<String>, locked_deps: Option<bool>, vendor: Option<bool>, + eslint: Option<String>, nodejs: Option<String>, python: Option<String>, full_bootstrap: Option<bool>, @@ -444,6 +446,7 @@ impl Config { }; + config.eslint = build.eslint.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2edc78ebaa94f..f1ad0e1f91ce1 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -609,6 +609,14 @@ impl Step for RustdocJS { "No nodejs found, skipping \"src/test/rustdoc-js\" tests" ); } + + if let Some(ref eslint) = builder.config.eslint { + let mut command = Command::new(eslint); + command.args(&["src/librustdoc/html/static"]); + builder.run(&mut command); + } else { + builder.info("No eslint found, skipping js linting"); + } } } From 1c029f4cb30990e92a685d24ffa0ae5a12c86356 Mon Sep 17 00:00:00 2001 From: John Heitmann <jheitmann@gmail.com> Date: Sat, 5 Jan 2019 00:34:13 -0800 Subject: [PATCH 124/124] Delete buggy code that is probably dead i_e is not defined, so in some cases this block cannot work. Furthermore, the toggle-wrapper is added after this block runs, so the hasClass(toggle-wrapper) check never seems to run. This appears to be dead code. --- src/librustdoc/html/static/main.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 29fa67bac3ae7..e376462d6e3cf 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2180,25 +2180,6 @@ if (!DOMTokenList.prototype.remove) { let showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; function buildToggleWrapper(e) { - if (hasClass(e, "autohide")) { - let wrap = e.previousElementSibling; - if (wrap && hasClass(wrap, "toggle-wrapper")) { - let inner_toggle = wrap.childNodes[0]; - let extra = e.childNodes[0].tagName === "H3"; - - e.style.display = "none"; - addClass(wrap, "collapsed"); - onEachLazy(inner_toggle.getElementsByClassName("inner"), function(e) { - e.innerHTML = labelForToggleButton(true); - }); - onEachLazy(inner_toggle.getElementsByClassName("toggle-label"), function(e) { - e.style.display = "inline-block"; - if (extra === true) { - i_e.innerHTML = " Show " + e.childNodes[0].innerHTML; - } - }); - } - } if (e.parentNode.id === "main") { let otherMessage = ""; let fontSize;