From 834347ddafee7c33f3fd556c4976275b1111dc8f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 9 Feb 2019 20:28:22 +0100 Subject: [PATCH 01/30] Add rustdoc JS non-std tests --- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 44 +++ src/test/rustdoc-js-not-std/basic.js | 7 + src/test/rustdoc-js-not-std/basic.rs | 1 + src/tools/rustdoc-js-not-std/tester.js | 365 +++++++++++++++++++++++++ src/tools/rustdoc-js/tester.js | 3 +- 6 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-js-not-std/basic.js create mode 100644 src/test/rustdoc-js-not-std/basic.rs create mode 100644 src/tools/rustdoc-js-not-std/tester.js diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 7e6c0a9f52aa2..71b9cd6f9fba4 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -406,6 +406,7 @@ impl<'a> Builder<'a> { test::Clippy, test::CompiletestTest, test::RustdocJS, + test::RustdocJSNotStd, test::RustdocTheme, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 51412f79c3d0c..7dcc10e8a0918 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -612,6 +612,50 @@ impl Step for RustdocJS { } } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustdocJSNotStd { + pub host: Interned, + pub target: Interned, + pub compiler: Compiler, +} + +impl Step for RustdocJSNotStd { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/test/rustdoc-js-not-std") + } + + fn make_run(run: RunConfig) { + let compiler = run.builder.compiler(run.builder.top_stage, run.host); + run.builder.ensure(RustdocJSNotStd { + host: run.host, + target: run.target, + compiler, + }); + } + + fn run(self, builder: &Builder) { + if let Some(ref nodejs) = builder.config.nodejs { + let mut command = Command::new(nodejs); + command.args(&["src/tools/rustdoc-js-not-std/tester.js", + &*self.host, + builder.top_stage.to_string().as_str()]); + builder.ensure(crate::doc::Std { + target: self.target, + stage: builder.top_stage, + }); + builder.run(&mut command); + } else { + builder.info( + "No nodejs found, skipping \"src/test/rustdoc-js-not-std\" tests" + ); + } + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocUi { pub host: Interned, diff --git a/src/test/rustdoc-js-not-std/basic.js b/src/test/rustdoc-js-not-std/basic.js new file mode 100644 index 0000000000000..d99b23468b60c --- /dev/null +++ b/src/test/rustdoc-js-not-std/basic.js @@ -0,0 +1,7 @@ +const QUERY = 'Fo'; + +const EXPECTED = { + 'others': [ + { 'path': 'basic', 'name': 'Foo' }, + ], +}; diff --git a/src/test/rustdoc-js-not-std/basic.rs b/src/test/rustdoc-js-not-std/basic.rs new file mode 100644 index 0000000000000..4a835673a596b --- /dev/null +++ b/src/test/rustdoc-js-not-std/basic.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/src/tools/rustdoc-js-not-std/tester.js b/src/tools/rustdoc-js-not-std/tester.js new file mode 100644 index 0000000000000..61490b2f48d03 --- /dev/null +++ b/src/tools/rustdoc-js-not-std/tester.js @@ -0,0 +1,365 @@ +const fs = require('fs'); +const { spawnSync } = require('child_process'); + +const TEST_FOLDER = 'src/test/rustdoc-js-not-std/'; + +function getNextStep(content, pos, stop) { + while (pos < content.length && content[pos] !== stop && + (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) { + pos += 1; + } + if (pos >= content.length) { + return null; + } + if (content[pos] !== stop) { + return pos * -1; + } + return pos; +} + +// Stupid function extractor based on indent. Doesn't support block +// comments. If someone puts a ' or an " in a block comment this +// will blow up. Template strings are not tested and might also be +// broken. +function extractFunction(content, functionName) { + var indent = 0; + var splitter = "function " + functionName + "("; + + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = start; + while (pos < content.length && content[pos] !== ')') { + pos += 1; + } + if (pos >= content.length) { + break; + } + pos = getNextStep(content, pos + 1, '{'); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + // Eat single-line comments + if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') { + do { + pos += 1; + } while (pos < content.length && content[pos] !== '\n'); + + // Eat quoted strings + } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") { + var stop = content[pos]; + var is_escaped = false; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + + // Otherwise, check for indent + } else if (content[pos] === '{') { + indent += 1; + } else if (content[pos] === '}') { + indent -= 1; + if (indent === 0) { + return content.slice(start, pos + 1); + } + } + pos += 1; + } + content = content.slice(start + 1); + } + return null; +} + +// Stupid function extractor for array. +function extractArrayVariable(content, arrayName) { + var splitter = "var " + arrayName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + pos = getNextStep(content, pos, '['); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ']' && + pos + 1 < content.length && + content[pos + 1] === ';') { + return content.slice(start, pos + 2); + } + pos += 1; + } + content = content.slice(start + 1); + } + return null; +} + +// Stupid function extractor for variable. +function extractVariable(content, varName) { + var splitter = "var " + varName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ';') { + return content.slice(start, pos + 1); + } + pos += 1; + } + content = content.slice(start + 1); + } + return null; +} + +function loadContent(content) { + var Module = module.constructor; + var m = new Module(); + m._compile(content, "tmp.js"); + m.exports.ignore_order = content.indexOf("\n// ignore-order\n") !== -1 || + content.startsWith("// ignore-order\n"); + m.exports.exact_check = content.indexOf("\n// exact-check\n") !== -1 || + content.startsWith("// exact-check\n"); + m.exports.should_fail = content.indexOf("\n// should-fail\n") !== -1 || + content.startsWith("// should-fail\n"); + return m.exports; +} + +function readFile(filePath) { + return fs.readFileSync(filePath, 'utf8'); +} + +function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { + var content = ''; + for (var i = 0; i < thingsToLoad.length; ++i) { + var tmp = funcToCall(fileContent, thingsToLoad[i]); + if (tmp === null) { + console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); + process.exit(1); + } + content += tmp; + content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';'; + } + return content; +} + +function lookForEntry(entry, data) { + for (var i = 0; i < data.length; ++i) { + var allGood = true; + for (var key in entry) { + if (!entry.hasOwnProperty(key)) { + continue; + } + var value = data[i][key]; + // To make our life easier, if there is a "parent" type, we add it to the path. + if (key === 'path' && data[i]['parent'] !== undefined) { + if (value.length > 0) { + value += '::' + data[i]['parent']['name']; + } else { + value = data[i]['parent']['name']; + } + } + if (value !== entry[key]) { + allGood = false; + break; + } + } + if (allGood === true) { + return i; + } + } + return null; +} + +function remove_docs(out_dir) { + spawnSync('rm', ['-rf', out_dir]); +} + +function build_docs(out_dir, rustdoc_path, file_to_document) { + remove_docs(out_dir); + var c = spawnSync(rustdoc_path, [file_to_document, '-o', out_dir]); + var s = ''; + if (c.error || c.stderr.length > 0) { + if (c.stderr.length > 0) { + s += '==> STDERR: ' + c.stderr + '\n'; + } + s += '==> ERROR: ' + c.error; + } + return s; +} + +function load_files(out_folder, crate) { + var mainJs = readFile(out_folder + "/main.js"); + var ALIASES = readFile(out_folder + "/aliases.js"); + var searchIndex = readFile(out_folder + "/search-index.js").split("\n"); + if (searchIndex[searchIndex.length - 1].length === 0) { + searchIndex.pop(); + } + searchIndex.pop(); + searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;'); + finalJS = ""; + + var arraysToLoad = ["itemTypes"]; + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", + "TY_PRIMITIVE", "TY_KEYWORD", + "levenshtein_row2"]; + // execQuery first parameter is built in getQuery (which takes in the search input). + // execQuery last parameter is built in buildIndex. + // buildIndex requires the hashmap from search-index. + var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", + "getQuery", "buildIndex", "execQuery", "execSearch"]; + + finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; + finalJS += 'var rootPath = "../";\n'; + finalJS += ALIASES; + finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); + finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); + finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); + + var loaded = loadContent(finalJS); + return [loaded, loaded.buildIndex(searchIndex.searchIndex)]; +} + +function main(argv) { + if (argv.length !== 4) { + console.error("USAGE: node tester.js [TOOLCHAIN] [STAGE]"); + return 1; + } + const toolchain = argv[2]; + const stage = argv[3]; + const rustdoc_path = './build/' + toolchain + '/stage' + stage + '/bin/rustdoc'; + + var errors = 0; + + fs.readdirSync(TEST_FOLDER).forEach(function(file) { + if (!file.endsWith('.js')) { + return; + } + var test_name = file.substring(0, file.length - 3); + process.stdout.write('Checking "' + test_name + '" ... '); + var rust_file = TEST_FOLDER + test_name + '.rs'; + + if (!fs.existsSync(rust_file)) { + console.error("FAILED"); + console.error("==> Missing '" + test_name + ".rs' file..."); + errors += 1; + return; + } + + var out_folder = "build/" + toolchain + "/stage" + stage + "/tests/rustdoc-js-not-std/" + + test_name; + + var ret = build_docs(out_folder, rustdoc_path, rust_file); + if (ret.length > 0) { + console.error("FAILED"); + console.error(ret); + errors += 1; + return; + } + + var [loaded, index] = load_files(out_folder, test_name); + var loadedFile = loadContent(readFile(TEST_FOLDER + file) + + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); + const expected = loadedFile.EXPECTED; + const query = loadedFile.QUERY; + const filter_crate = loadedFile.FILTER_CRATE; + const ignore_order = loadedFile.ignore_order; + const exact_check = loadedFile.exact_check; + const should_fail = loadedFile.should_fail; + var results = loaded.execSearch(loaded.getQuery(query), index); + var error_text = []; + for (var key in expected) { + if (!expected.hasOwnProperty(key)) { + continue; + } + if (!results.hasOwnProperty(key)) { + error_text.push('==> Unknown key "' + key + '"'); + break; + } + var entry = expected[key]; + var prev_pos = -1; + for (var i = 0; i < entry.length; ++i) { + var entry_pos = lookForEntry(entry[i], results[key]); + if (entry_pos === null) { + error_text.push("==> Result not found in '" + key + "': '" + + JSON.stringify(entry[i]) + "'"); + } else if (exact_check === true && prev_pos + 1 !== entry_pos) { + error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " + + "expected '" + JSON.stringify(entry[i]) + "' but found '" + + JSON.stringify(results[key][i]) + "'"); + } else if (ignore_order === false && entry_pos < prev_pos) { + error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + + " before '" + JSON.stringify(results[key][entry_pos]) + "'"); + } else { + prev_pos = entry_pos; + } + } + } + if (error_text.length === 0 && should_fail === true) { + errors += 1; + console.error("FAILED"); + console.error("==> Test was supposed to fail but all items were found..."); + } else if (error_text.length !== 0 && should_fail === false) { + errors += 1; + console.error("FAILED"); + console.error(error_text.join("\n")); + } else { + // In this case, we remove the docs, no need to keep them around. + remove_docs(out_folder); + console.log("OK"); + } + }); + return errors; +} + +process.exit(main(process.argv)); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c41da93a98310..38fdcb4f468cf 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -221,7 +221,8 @@ function lookForEntry(entry, data) { function main(argv) { if (argv.length !== 3) { - console.error("Expected toolchain to check as argument (for example 'x86_64-apple-darwin'"); + console.error("Expected toolchain to check as argument (for example \ + 'x86_64-apple-darwin')"); return 1; } var toolchain = argv[2]; From aa3ca321e92c541dce363634c9cea7cf23689a5e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 24 Feb 2019 00:08:43 +0100 Subject: [PATCH 02/30] Rename rustdoc js test suites --- src/bootstrap/builder.rs | 2 +- src/bootstrap/test.rs | 18 ++--- src/test/rustdoc-js-not-std/basic.js | 7 -- .../{rustdoc-js => rustdoc-js-std}/alias-1.js | 0 .../{rustdoc-js => rustdoc-js-std}/alias-2.js | 0 .../{rustdoc-js => rustdoc-js-std}/alias-3.js | 0 .../{rustdoc-js => rustdoc-js-std}/alias.js | 0 src/test/rustdoc-js-std/basic.js | 15 ++++ .../deduplication.js | 0 .../enum-option.js | 0 .../filter-crate.js | 0 .../fn-forget.js | 0 .../{rustdoc-js => rustdoc-js-std}/from_u.js | 0 .../{rustdoc-js => rustdoc-js-std}/keyword.js | 0 .../macro-check.js | 0 .../macro-print.js | 0 .../multi-query.js | 0 .../{rustdoc-js => rustdoc-js-std}/never.js | 0 .../{rustdoc-js => rustdoc-js-std}/quoted.js | 0 .../should-fail.js | 0 .../string-from_ut.js | 0 .../struct-vec.js | 0 .../{rustdoc-js => rustdoc-js-std}/vec-new.js | 0 src/test/rustdoc-js/basic.js | 12 +-- .../basic.rs | 0 .../tester.js | 74 ++++--------------- src/tools/rustdoc-js/tester.js | 65 +++++++++++++--- 27 files changed, 93 insertions(+), 100 deletions(-) delete mode 100644 src/test/rustdoc-js-not-std/basic.js rename src/test/{rustdoc-js => rustdoc-js-std}/alias-1.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/alias-2.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/alias-3.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/alias.js (100%) create mode 100644 src/test/rustdoc-js-std/basic.js rename src/test/{rustdoc-js => rustdoc-js-std}/deduplication.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/enum-option.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/filter-crate.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/fn-forget.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/from_u.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/keyword.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/macro-check.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/macro-print.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/multi-query.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/never.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/quoted.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/should-fail.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/string-from_ut.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/struct-vec.js (100%) rename src/test/{rustdoc-js => rustdoc-js-std}/vec-new.js (100%) rename src/test/{rustdoc-js-not-std => rustdoc-js}/basic.rs (100%) rename src/tools/{rustdoc-js-not-std => rustdoc-js-std}/tester.js (83%) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 71b9cd6f9fba4..a471af257665f 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -405,7 +405,7 @@ impl<'a> Builder<'a> { test::Miri, test::Clippy, test::CompiletestTest, - test::RustdocJS, + test::RustdocJSStd, test::RustdocJSNotStd, test::RustdocTheme, // Run bootstrap close to the end as it's unlikely to fail diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7dcc10e8a0918..c724d75c2dc06 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -574,22 +574,22 @@ impl Step for RustdocTheme { } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustdocJS { +pub struct RustdocJSStd { pub host: Interned, pub target: Interned, } -impl Step for RustdocJS { +impl Step for RustdocJSStd { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/test/rustdoc-js") + run.path("src/test/rustdoc-js-std") } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustdocJS { + run.builder.ensure(RustdocJSStd { host: run.host, target: run.target, }); @@ -598,7 +598,7 @@ impl Step for RustdocJS { fn run(self, builder: &Builder<'_>) { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); - command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]); + command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]); builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage, @@ -606,7 +606,7 @@ impl Step for RustdocJS { builder.run(&mut command); } else { builder.info( - "No nodejs found, skipping \"src/test/rustdoc-js\" tests" + "No nodejs found, skipping \"src/test/rustdoc-js-std\" tests" ); } } @@ -625,7 +625,7 @@ impl Step for RustdocJSNotStd { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/test/rustdoc-js-not-std") + run.path("src/test/rustdoc-js") } fn make_run(run: RunConfig) { @@ -640,7 +640,7 @@ impl Step for RustdocJSNotStd { fn run(self, builder: &Builder) { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); - command.args(&["src/tools/rustdoc-js-not-std/tester.js", + command.args(&["src/tools/rustdoc-js/tester.js", &*self.host, builder.top_stage.to_string().as_str()]); builder.ensure(crate::doc::Std { @@ -650,7 +650,7 @@ impl Step for RustdocJSNotStd { builder.run(&mut command); } else { builder.info( - "No nodejs found, skipping \"src/test/rustdoc-js-not-std\" tests" + "No nodejs found, skipping \"src/test/rustdoc-js\" tests" ); } } diff --git a/src/test/rustdoc-js-not-std/basic.js b/src/test/rustdoc-js-not-std/basic.js deleted file mode 100644 index d99b23468b60c..0000000000000 --- a/src/test/rustdoc-js-not-std/basic.js +++ /dev/null @@ -1,7 +0,0 @@ -const QUERY = 'Fo'; - -const EXPECTED = { - 'others': [ - { 'path': 'basic', 'name': 'Foo' }, - ], -}; diff --git a/src/test/rustdoc-js/alias-1.js b/src/test/rustdoc-js-std/alias-1.js similarity index 100% rename from src/test/rustdoc-js/alias-1.js rename to src/test/rustdoc-js-std/alias-1.js diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js-std/alias-2.js similarity index 100% rename from src/test/rustdoc-js/alias-2.js rename to src/test/rustdoc-js-std/alias-2.js diff --git a/src/test/rustdoc-js/alias-3.js b/src/test/rustdoc-js-std/alias-3.js similarity index 100% rename from src/test/rustdoc-js/alias-3.js rename to src/test/rustdoc-js-std/alias-3.js diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js-std/alias.js similarity index 100% rename from src/test/rustdoc-js/alias.js rename to src/test/rustdoc-js-std/alias.js diff --git a/src/test/rustdoc-js-std/basic.js b/src/test/rustdoc-js-std/basic.js new file mode 100644 index 0000000000000..824cac7108332 --- /dev/null +++ b/src/test/rustdoc-js-std/basic.js @@ -0,0 +1,15 @@ +const QUERY = 'String'; + +const EXPECTED = { + 'others': [ + { 'path': 'std::string', 'name': 'String' }, + { 'path': 'std::ffi', 'name': 'CString' }, + { 'path': 'std::ffi', 'name': 'OsString' }, + ], + 'in_args': [ + { 'path': 'std::str', 'name': 'eq' }, + ], + 'returned': [ + { 'path': 'std::string::String', 'name': 'add' }, + ], +}; diff --git a/src/test/rustdoc-js/deduplication.js b/src/test/rustdoc-js-std/deduplication.js similarity index 100% rename from src/test/rustdoc-js/deduplication.js rename to src/test/rustdoc-js-std/deduplication.js diff --git a/src/test/rustdoc-js/enum-option.js b/src/test/rustdoc-js-std/enum-option.js similarity index 100% rename from src/test/rustdoc-js/enum-option.js rename to src/test/rustdoc-js-std/enum-option.js diff --git a/src/test/rustdoc-js/filter-crate.js b/src/test/rustdoc-js-std/filter-crate.js similarity index 100% rename from src/test/rustdoc-js/filter-crate.js rename to src/test/rustdoc-js-std/filter-crate.js diff --git a/src/test/rustdoc-js/fn-forget.js b/src/test/rustdoc-js-std/fn-forget.js similarity index 100% rename from src/test/rustdoc-js/fn-forget.js rename to src/test/rustdoc-js-std/fn-forget.js diff --git a/src/test/rustdoc-js/from_u.js b/src/test/rustdoc-js-std/from_u.js similarity index 100% rename from src/test/rustdoc-js/from_u.js rename to src/test/rustdoc-js-std/from_u.js diff --git a/src/test/rustdoc-js/keyword.js b/src/test/rustdoc-js-std/keyword.js similarity index 100% rename from src/test/rustdoc-js/keyword.js rename to src/test/rustdoc-js-std/keyword.js diff --git a/src/test/rustdoc-js/macro-check.js b/src/test/rustdoc-js-std/macro-check.js similarity index 100% rename from src/test/rustdoc-js/macro-check.js rename to src/test/rustdoc-js-std/macro-check.js diff --git a/src/test/rustdoc-js/macro-print.js b/src/test/rustdoc-js-std/macro-print.js similarity index 100% rename from src/test/rustdoc-js/macro-print.js rename to src/test/rustdoc-js-std/macro-print.js diff --git a/src/test/rustdoc-js/multi-query.js b/src/test/rustdoc-js-std/multi-query.js similarity index 100% rename from src/test/rustdoc-js/multi-query.js rename to src/test/rustdoc-js-std/multi-query.js diff --git a/src/test/rustdoc-js/never.js b/src/test/rustdoc-js-std/never.js similarity index 100% rename from src/test/rustdoc-js/never.js rename to src/test/rustdoc-js-std/never.js diff --git a/src/test/rustdoc-js/quoted.js b/src/test/rustdoc-js-std/quoted.js similarity index 100% rename from src/test/rustdoc-js/quoted.js rename to src/test/rustdoc-js-std/quoted.js diff --git a/src/test/rustdoc-js/should-fail.js b/src/test/rustdoc-js-std/should-fail.js similarity index 100% rename from src/test/rustdoc-js/should-fail.js rename to src/test/rustdoc-js-std/should-fail.js diff --git a/src/test/rustdoc-js/string-from_ut.js b/src/test/rustdoc-js-std/string-from_ut.js similarity index 100% rename from src/test/rustdoc-js/string-from_ut.js rename to src/test/rustdoc-js-std/string-from_ut.js diff --git a/src/test/rustdoc-js/struct-vec.js b/src/test/rustdoc-js-std/struct-vec.js similarity index 100% rename from src/test/rustdoc-js/struct-vec.js rename to src/test/rustdoc-js-std/struct-vec.js diff --git a/src/test/rustdoc-js/vec-new.js b/src/test/rustdoc-js-std/vec-new.js similarity index 100% rename from src/test/rustdoc-js/vec-new.js rename to src/test/rustdoc-js-std/vec-new.js diff --git a/src/test/rustdoc-js/basic.js b/src/test/rustdoc-js/basic.js index 824cac7108332..d99b23468b60c 100644 --- a/src/test/rustdoc-js/basic.js +++ b/src/test/rustdoc-js/basic.js @@ -1,15 +1,7 @@ -const QUERY = 'String'; +const QUERY = 'Fo'; const EXPECTED = { 'others': [ - { 'path': 'std::string', 'name': 'String' }, - { 'path': 'std::ffi', 'name': 'CString' }, - { 'path': 'std::ffi', 'name': 'OsString' }, - ], - 'in_args': [ - { 'path': 'std::str', 'name': 'eq' }, - ], - 'returned': [ - { 'path': 'std::string::String', 'name': 'add' }, + { 'path': 'basic', 'name': 'Foo' }, ], }; diff --git a/src/test/rustdoc-js-not-std/basic.rs b/src/test/rustdoc-js/basic.rs similarity index 100% rename from src/test/rustdoc-js-not-std/basic.rs rename to src/test/rustdoc-js/basic.rs diff --git a/src/tools/rustdoc-js-not-std/tester.js b/src/tools/rustdoc-js-std/tester.js similarity index 83% rename from src/tools/rustdoc-js-not-std/tester.js rename to src/tools/rustdoc-js-std/tester.js index 61490b2f48d03..f49dd86c8c32d 100644 --- a/src/tools/rustdoc-js-not-std/tester.js +++ b/src/tools/rustdoc-js-std/tester.js @@ -1,7 +1,6 @@ const fs = require('fs'); -const { spawnSync } = require('child_process'); -const TEST_FOLDER = 'src/test/rustdoc-js-not-std/'; +const TEST_FOLDER = 'src/test/rustdoc-js-std/'; function getNextStep(content, pos, stop) { while (pos < content.length && content[pos] !== stop && @@ -220,27 +219,17 @@ function lookForEntry(entry, data) { return null; } -function remove_docs(out_dir) { - spawnSync('rm', ['-rf', out_dir]); -} - -function build_docs(out_dir, rustdoc_path, file_to_document) { - remove_docs(out_dir); - var c = spawnSync(rustdoc_path, [file_to_document, '-o', out_dir]); - var s = ''; - if (c.error || c.stderr.length > 0) { - if (c.stderr.length > 0) { - s += '==> STDERR: ' + c.stderr + '\n'; - } - s += '==> ERROR: ' + c.error; +function main(argv) { + if (argv.length !== 3) { + console.error("Expected toolchain to check as argument (for example \ + 'x86_64-apple-darwin')"); + return 1; } - return s; -} + var toolchain = argv[2]; -function load_files(out_folder, crate) { - var mainJs = readFile(out_folder + "/main.js"); - var ALIASES = readFile(out_folder + "/aliases.js"); - var searchIndex = readFile(out_folder + "/search-index.js").split("\n"); + var mainJs = readFile("build/" + toolchain + "/doc/main.js"); + var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js"); + var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n"); if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -259,7 +248,7 @@ function load_files(out_folder, crate) { var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery", "execSearch"]; - finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; + finalJS += 'window = { "currentCrate": "std" };\n'; finalJS += 'var rootPath = "../";\n'; finalJS += ALIASES; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); @@ -267,47 +256,11 @@ function load_files(out_folder, crate) { finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); - return [loaded, loaded.buildIndex(searchIndex.searchIndex)]; -} - -function main(argv) { - if (argv.length !== 4) { - console.error("USAGE: node tester.js [TOOLCHAIN] [STAGE]"); - return 1; - } - const toolchain = argv[2]; - const stage = argv[3]; - const rustdoc_path = './build/' + toolchain + '/stage' + stage + '/bin/rustdoc'; + var index = loaded.buildIndex(searchIndex.searchIndex); var errors = 0; fs.readdirSync(TEST_FOLDER).forEach(function(file) { - if (!file.endsWith('.js')) { - return; - } - var test_name = file.substring(0, file.length - 3); - process.stdout.write('Checking "' + test_name + '" ... '); - var rust_file = TEST_FOLDER + test_name + '.rs'; - - if (!fs.existsSync(rust_file)) { - console.error("FAILED"); - console.error("==> Missing '" + test_name + ".rs' file..."); - errors += 1; - return; - } - - var out_folder = "build/" + toolchain + "/stage" + stage + "/tests/rustdoc-js-not-std/" + - test_name; - - var ret = build_docs(out_folder, rustdoc_path, rust_file); - if (ret.length > 0) { - console.error("FAILED"); - console.error(ret); - errors += 1; - return; - } - - var [loaded, index] = load_files(out_folder, test_name); var loadedFile = loadContent(readFile(TEST_FOLDER + file) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; @@ -317,6 +270,7 @@ function main(argv) { const exact_check = loadedFile.exact_check; const should_fail = loadedFile.should_fail; var results = loaded.execSearch(loaded.getQuery(query), index); + process.stdout.write('Checking "' + file + '" ... '); var error_text = []; for (var key in expected) { if (!expected.hasOwnProperty(key)) { @@ -354,8 +308,6 @@ function main(argv) { console.error("FAILED"); console.error(error_text.join("\n")); } else { - // In this case, we remove the docs, no need to keep them around. - remove_docs(out_folder); console.log("OK"); } }); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 38fdcb4f468cf..f7c15eaf1b07d 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const { spawnSync } = require('child_process'); const TEST_FOLDER = 'src/test/rustdoc-js/'; @@ -219,17 +220,22 @@ function lookForEntry(entry, data) { return null; } -function main(argv) { - if (argv.length !== 3) { - console.error("Expected toolchain to check as argument (for example \ - 'x86_64-apple-darwin')"); - return 1; +function build_docs(out_dir, rustdoc_path, file_to_document) { + var c = spawnSync(rustdoc_path, [file_to_document, '-o', out_dir]); + var s = ''; + if (c.error || c.stderr.length > 0) { + if (c.stderr.length > 0) { + s += '==> STDERR: ' + c.stderr + '\n'; + } + s += '==> ERROR: ' + c.error; } - var toolchain = argv[2]; + return s; +} - var mainJs = readFile("build/" + toolchain + "/doc/main.js"); - var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js"); - var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n"); +function load_files(out_folder, crate) { + var mainJs = readFile(out_folder + "/main.js"); + var ALIASES = readFile(out_folder + "/aliases.js"); + var searchIndex = readFile(out_folder + "/search-index.js").split("\n"); if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -248,7 +254,7 @@ function main(argv) { var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", "getQuery", "buildIndex", "execQuery", "execSearch"]; - finalJS += 'window = { "currentCrate": "std" };\n'; + finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; finalJS += ALIASES; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); @@ -256,11 +262,47 @@ function main(argv) { finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); - var index = loaded.buildIndex(searchIndex.searchIndex); + return [loaded, loaded.buildIndex(searchIndex.searchIndex)]; +} + +function main(argv) { + if (argv.length !== 4) { + console.error("USAGE: node tester.js [TOOLCHAIN] [STAGE]"); + return 1; + } + const toolchain = argv[2]; + const stage = argv[3]; + const rustdoc_path = './build/' + toolchain + '/stage' + stage + '/bin/rustdoc'; var errors = 0; fs.readdirSync(TEST_FOLDER).forEach(function(file) { + if (!file.endsWith('.js')) { + return; + } + var test_name = file.substring(0, file.length - 3); + process.stdout.write('Checking "' + test_name + '" ... '); + var rust_file = TEST_FOLDER + test_name + '.rs'; + + if (!fs.existsSync(rust_file)) { + console.error("FAILED"); + console.error("==> Missing '" + test_name + ".rs' file..."); + errors += 1; + return; + } + + var out_folder = "build/" + toolchain + "/stage" + stage + "/tests/rustdoc-js/" + + test_name; + + var ret = build_docs(out_folder, rustdoc_path, rust_file); + if (ret.length > 0) { + console.error("FAILED"); + console.error(ret); + errors += 1; + return; + } + + var [loaded, index] = load_files(out_folder, test_name); var loadedFile = loadContent(readFile(TEST_FOLDER + file) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; @@ -270,7 +312,6 @@ function main(argv) { const exact_check = loadedFile.exact_check; const should_fail = loadedFile.should_fail; var results = loaded.execSearch(loaded.getQuery(query), index); - process.stdout.write('Checking "' + file + '" ... '); var error_text = []; for (var key in expected) { if (!expected.hasOwnProperty(key)) { From be23cd9a2d32295240e265aa2ed38bace71aca65 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 24 Feb 2019 01:04:07 +0100 Subject: [PATCH 03/30] Move documentation build into bootstrap --- src/bootstrap/test.rs | 46 ++++++++++++++++++++++++--- src/tools/rustdoc-js/tester.js | 58 ++++++++++------------------------ 2 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c724d75c2dc06..83066468cd435 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -4,7 +4,7 @@ //! our CI. use std::env; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fmt; use std::fs; use std::iter; @@ -639,14 +639,50 @@ impl Step for RustdocJSNotStd { fn run(self, builder: &Builder) { if let Some(ref nodejs) = builder.config.nodejs { - let mut command = Command::new(nodejs); - command.args(&["src/tools/rustdoc-js/tester.js", - &*self.host, - builder.top_stage.to_string().as_str()]); builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage, }); + + let mut tests_to_run = Vec::new(); + let out = Path::new("build").join(&*self.host) + .join(&format!("stage{}", + builder.top_stage.to_string().as_str())) + .join("tests") + .join("rustdoc-js"); + + if let Ok(it) = fs::read_dir("src/test/rustdoc-js/") { + for entry in it { + if let Ok(entry) = entry { + let path = entry.path(); + if path.extension() != Some(&OsStr::new("rs")) || !path.is_file() { + continue + } + let path_clone = path.clone(); + let file_stem = path_clone.file_stem().expect("cannot get file stem"); + let out = out.join(file_stem); + let mut cmd = builder.rustdoc_cmd(self.host); + cmd.arg("-o"); + cmd.arg(out); + cmd.arg(path); + if if builder.config.verbose_tests { + try_run(builder, &mut cmd) + } else { + try_run_quiet(builder, &mut cmd) + } { + tests_to_run.push(file_stem.to_os_string()); + } + } + } + } + assert!(!tests_to_run.is_empty(), "no rustdoc-js test generated..."); + + tests_to_run.insert(0, "src/tools/rustdoc-js/tester.js".into()); + tests_to_run.insert(1, out.into()); + + let mut command = Command::new(nodejs); + command.args(&tests_to_run); + builder.run(&mut command); } else { builder.info( diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index f7c15eaf1b07d..833ce5d137047 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -220,18 +220,6 @@ function lookForEntry(entry, data) { return null; } -function build_docs(out_dir, rustdoc_path, file_to_document) { - var c = spawnSync(rustdoc_path, [file_to_document, '-o', out_dir]); - var s = ''; - if (c.error || c.stderr.length > 0) { - if (c.stderr.length > 0) { - s += '==> STDERR: ' + c.stderr + '\n'; - } - s += '==> ERROR: ' + c.error; - } - return s; -} - function load_files(out_folder, crate) { var mainJs = readFile(out_folder + "/main.js"); var ALIASES = readFile(out_folder + "/aliases.js"); @@ -266,44 +254,32 @@ function load_files(out_folder, crate) { } function main(argv) { - if (argv.length !== 4) { - console.error("USAGE: node tester.js [TOOLCHAIN] [STAGE]"); + if (argv.length < 4) { + console.error("USAGE: node tester.js OUT_FOLDER [TESTS]"); return 1; } - const toolchain = argv[2]; - const stage = argv[3]; - const rustdoc_path = './build/' + toolchain + '/stage' + stage + '/bin/rustdoc'; + if (argv[2].substr(-1) !== "/") { + argv[2] += "/"; + } + const out_folder = argv[2]; var errors = 0; - fs.readdirSync(TEST_FOLDER).forEach(function(file) { - if (!file.endsWith('.js')) { - return; - } - var test_name = file.substring(0, file.length - 3); - process.stdout.write('Checking "' + test_name + '" ... '); - var rust_file = TEST_FOLDER + test_name + '.rs'; + for (var j = 3; j < argv.length; ++j) { + const test_name = argv[j]; - if (!fs.existsSync(rust_file)) { - console.error("FAILED"); - console.error("==> Missing '" + test_name + ".rs' file..."); + process.stdout.write('Checking "' + test_name + '" ... '); + if (!fs.existsSync(TEST_FOLDER + test_name + ".js")) { errors += 1; - return; - } - - var out_folder = "build/" + toolchain + "/stage" + stage + "/tests/rustdoc-js/" + - test_name; - - var ret = build_docs(out_folder, rustdoc_path, rust_file); - if (ret.length > 0) { console.error("FAILED"); - console.error(ret); - errors += 1; - return; + console.error("==> Missing '" + test_name + ".js' file..."); + continue; } - var [loaded, index] = load_files(out_folder, test_name); - var loadedFile = loadContent(readFile(TEST_FOLDER + file) + + const test_out_folder = out_folder + test_name; + + var [loaded, index] = load_files(test_out_folder, test_name); + var loadedFile = loadContent(readFile(TEST_FOLDER + test_name + ".js") + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; @@ -351,7 +327,7 @@ function main(argv) { } else { console.log("OK"); } - }); + } return errors; } From 240fad04f1c5517d5d38ab62c321f09c35a468d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Feb 2019 17:47:12 +0100 Subject: [PATCH 04/30] Update to last updates --- src/bootstrap/test.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 83066468cd435..97a5c500b1a47 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -624,11 +624,11 @@ impl Step for RustdocJSNotStd { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(run: ShouldRun) -> ShouldRun { + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/test/rustdoc-js") } - fn make_run(run: RunConfig) { + fn make_run(run: RunConfig<'_>) { let compiler = run.builder.compiler(run.builder.top_stage, run.host); run.builder.ensure(RustdocJSNotStd { host: run.host, @@ -637,7 +637,7 @@ impl Step for RustdocJSNotStd { }); } - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder<'_>) { if let Some(ref nodejs) = builder.config.nodejs { builder.ensure(crate::doc::Std { target: self.target, From 405d95080288dc760e117a506278d968d57dfe09 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Feb 2019 18:08:48 +0100 Subject: [PATCH 05/30] Move rustdoc-js testing into compiletest --- src/bootstrap/test.rs | 62 ++++++---------------------- src/test/rustdoc-js/basic.rs | 1 + src/tools/compiletest/src/common.rs | 3 ++ src/tools/compiletest/src/runtest.rs | 29 +++++++++++-- 4 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 97a5c500b1a47..b7323b2eadc3d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -4,7 +4,7 @@ //! our CI. use std::env; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsString; use std::fmt; use std::fs; use std::iter; @@ -638,52 +638,15 @@ impl Step for RustdocJSNotStd { } fn run(self, builder: &Builder<'_>) { - if let Some(ref nodejs) = builder.config.nodejs { - builder.ensure(crate::doc::Std { + if builder.config.nodejs.is_some() { + builder.ensure(Compiletest { + compiler: self.compiler, target: self.target, - stage: builder.top_stage, + mode: "js-doc-test", + suite: "rustdoc-js", + path: None, + compare_mode: None, }); - - let mut tests_to_run = Vec::new(); - let out = Path::new("build").join(&*self.host) - .join(&format!("stage{}", - builder.top_stage.to_string().as_str())) - .join("tests") - .join("rustdoc-js"); - - if let Ok(it) = fs::read_dir("src/test/rustdoc-js/") { - for entry in it { - if let Ok(entry) = entry { - let path = entry.path(); - if path.extension() != Some(&OsStr::new("rs")) || !path.is_file() { - continue - } - let path_clone = path.clone(); - let file_stem = path_clone.file_stem().expect("cannot get file stem"); - let out = out.join(file_stem); - let mut cmd = builder.rustdoc_cmd(self.host); - cmd.arg("-o"); - cmd.arg(out); - cmd.arg(path); - if if builder.config.verbose_tests { - try_run(builder, &mut cmd) - } else { - try_run_quiet(builder, &mut cmd) - } { - tests_to_run.push(file_stem.to_os_string()); - } - } - } - } - assert!(!tests_to_run.is_empty(), "no rustdoc-js test generated..."); - - tests_to_run.insert(0, "src/tools/rustdoc-js/tester.js".into()); - tests_to_run.insert(1, out.into()); - - let mut command = Command::new(nodejs); - command.args(&tests_to_run); - - builder.run(&mut command); } else { builder.info( "No nodejs found, skipping \"src/test/rustdoc-js\" tests" @@ -1070,12 +1033,13 @@ impl Step for Compiletest { .arg(builder.sysroot_libdir(compiler, target)); cmd.arg("--rustc-path").arg(builder.rustc(compiler)); - let is_rustdoc_ui = suite.ends_with("rustdoc-ui"); + let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js"); // Avoid depending on rustdoc when we don't need it. if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) - || (mode == "ui" && is_rustdoc_ui) + || (mode == "ui" && is_rustdoc) + || mode == "js-doc-test" { cmd.arg("--rustdoc-path") .arg(builder.rustdoc(compiler.host)); @@ -1109,12 +1073,12 @@ impl Step for Compiletest { cmd.arg("--nodejs").arg(nodejs); } - let mut flags = if is_rustdoc_ui { + let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; - if !is_rustdoc_ui { + if !is_rustdoc { if builder.config.rust_optimize_tests { flags.push("-O".to_string()); } diff --git a/src/test/rustdoc-js/basic.rs b/src/test/rustdoc-js/basic.rs index 4a835673a596b..1b4963fcebea8 100644 --- a/src/test/rustdoc-js/basic.rs +++ b/src/test/rustdoc-js/basic.rs @@ -1 +1,2 @@ +/// Foo pub struct Foo; diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 6b3117a1f74f4..f0991c8cdb547 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -24,6 +24,7 @@ pub enum Mode { Incremental, RunMake, Ui, + JsDocTest, MirOpt, } @@ -59,6 +60,7 @@ impl FromStr for Mode { "incremental" => Ok(Incremental), "run-make" => Ok(RunMake), "ui" => Ok(Ui), + "js-doc-test" => Ok(JsDocTest), "mir-opt" => Ok(MirOpt), _ => Err(()), } @@ -82,6 +84,7 @@ impl fmt::Display for Mode { Incremental => "incremental", RunMake => "run-make", Ui => "ui", + JsDocTest => "js-doc-test", MirOpt => "mir-opt", }; fmt::Display::fmt(s, f) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bac41a7c57904..f7c02e831a9aa 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4,7 +4,7 @@ use crate::common::{output_base_dir, output_base_name, output_testname_unique}; use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; -use crate::common::{Incremental, MirOpt, RunMake, Ui}; +use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest}; use diff; use crate::errors::{self, Error, ErrorKind}; use filetime::FileTime; @@ -275,6 +275,7 @@ impl<'test> TestCx<'test> { RunMake => self.run_rmake_test(), RunPass | Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), + JsDocTest => self.run_js_doc_test(), } } @@ -290,7 +291,7 @@ impl<'test> TestCx<'test> { fn should_compile_successfully(&self) -> bool { match self.config.mode { CompileFail => self.props.compile_pass, - RunPass => true, + RunPass | JsDocTest => true, Ui => self.props.compile_pass, Incremental => { let revision = self.revision @@ -1712,7 +1713,8 @@ impl<'test> TestCx<'test> { } fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command { - let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui"); + let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") || + self.config.src_base.ends_with("rustdoc-js"); let mut rustc = if !is_rustdoc { Command::new(&self.config.rustc_path) } else { @@ -1802,7 +1804,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb - | Codegen | Rustdoc | RunMake | CodegenUnits => { + | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest => { // do not use JSON output } } @@ -2710,6 +2712,25 @@ impl<'test> TestCx<'test> { fs::remove_dir(path) } + fn run_js_doc_test(&self) { + if let Some(nodejs) = &self.config.nodejs { + let out_dir = self.output_base_dir(); + + self.document(&out_dir); + + let root = self.config.find_rust_src_root().unwrap(); + let res = self.cmd2procres( + Command::new(&nodejs) + .arg(root.join("src/tools/rustdoc-js/tester.js")) + .arg(out_dir.parent().expect("no parent")) + .arg(&self.testpaths.file.file_stem().expect("couldn't get file stem")), + ); + if !res.status.success() { + self.fatal_proc_rec("rustdoc-js test failed!", &res); + } + } + } + fn run_ui_test(&self) { // if the user specified a format in the ui test // print the output to the stderr file, otherwise extract From fb98ca716fca8d9342f4cf308622a8e78c072fb7 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 28 Feb 2019 10:25:54 +0100 Subject: [PATCH 06/30] fs::copy() linux: set file mode early A convenience method like fs::copy() should try to prevent pitfalls a normal user doesn't think about. In case of an empty umask, setting the file mode early prevents temporarily world readable or even writeable files, because the default mode is 0o666. In case the target is a named pipe or special device node, setting the file mode can lead to unwanted side effects, like setting permissons on `/dev/stdout` or for root setting permissions on `/dev/null`. copy_file_range() returns EINVAL, if the destination is a FIFO/pipe or a device like "/dev/null", so fallback to io::copy, too. Fixes: https://github.com/rust-lang/rust/issues/26933 Fixed: https://github.com/rust-lang/rust/issues/37885 --- src/libstd/sys/unix/fs.rs | 41 +++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 3b80b475a93db..38052cbde601a 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -847,7 +847,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use crate::cmp; - use crate::fs::File; + use crate::fs::{File, OpenOptions}; + use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt}; use crate::sync::atomic::{AtomicBool, Ordering}; // Kernel prior to 4.5 don't have copy_file_range @@ -873,18 +874,35 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { ) } - if !from.is_file() { - return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing regular file")) - } - let mut reader = File::open(from)?; - let mut writer = File::create(to)?; + let (perm, len) = { let metadata = reader.metadata()?; - (metadata.permissions(), metadata.size()) + if !metadata.is_file() { + return Err(Error::new( + ErrorKind::InvalidInput, + "the source path is not an existing regular file", + )); + } + (metadata.permissions(), metadata.len()) }; + let mut writer = OpenOptions::new() + // create the file with the correct mode right away + .mode(perm.mode()) + .write(true) + .create(true) + .truncate(true) + .open(to)?; + + let writer_metadata = writer.metadata()?; + if writer_metadata.is_file() { + // Set the correct file permissions, in case the file already existed. + // Don't set the permissions on already existing non-files like + // pipes/FIFOs or device nodes. + writer.set_permissions(perm)?; + } + let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); let mut written = 0u64; while written < len { @@ -919,21 +937,20 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { match err.raw_os_error() { Some(os_err) if os_err == libc::ENOSYS || os_err == libc::EXDEV + || os_err == libc::EINVAL || os_err == libc::EPERM => { // Try fallback io::copy if either: // - Kernel version is < 4.5 (ENOSYS) // - Files are mounted on different fs (EXDEV) // - copy_file_range is disallowed, for example by seccomp (EPERM) + // - copy_file_range cannot be used with pipes or device nodes (EINVAL) assert_eq!(written, 0); - let ret = io::copy(&mut reader, &mut writer)?; - writer.set_permissions(perm)?; - return Ok(ret) + return io::copy(&mut reader, &mut writer); }, _ => return Err(err), } } } } - writer.set_permissions(perm)?; Ok(written) } From 204f087daf6570824832eec56b24d9cd8cbf4a70 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 1 Mar 2019 10:18:50 +0100 Subject: [PATCH 07/30] librustc_interface: Update scoped-tls to 1.0 Done previously as a part of https://github.com/rust-lang/rust/pull/58748 --- Cargo.lock | 2 +- src/librustc_interface/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 381322bc421d4..2e4fbf02a0e53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2774,7 +2774,7 @@ dependencies = [ "rustc_resolve 0.0.0", "rustc_traits 0.0.0", "rustc_typeck 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 1acd3dfc7656a..294e23dc6177c 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["dylib"] log = "0.4" rustc-rayon = "0.1.1" smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } -scoped-tls = { version = "0.1.1", features = ["nightly"] } +scoped-tls = "1.0" syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } From 196e02192f88fdfdcf131b094882913590d34eb4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 Mar 2019 17:03:15 +0100 Subject: [PATCH 08/30] Prevent cache issues on version updates --- src/bootstrap/doc.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 40f0e5ede8bd7..1891334ac2dd1 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -343,12 +343,10 @@ fn invoke_rustdoc( .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&favicon) .arg("--markdown-no-toc") - .arg("--markdown-playground-url") - .arg("https://play.rust-lang.org/") - .arg("-o").arg(&out) - .arg(&path) - .arg("--markdown-css") - .arg("../rust.css"); + .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) + .arg("--markdown-playground-url").arg("https://play.rust-lang.org/") + .arg("-o").arg(&out).arg(&path) + .arg("--markdown-css").arg("../rust.css"); builder.run(&mut cmd); } @@ -430,9 +428,9 @@ impl Step for Standalone { .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&favicon) .arg("--markdown-no-toc") + .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page").arg(&builder.src.join("src/doc/index.md")) - .arg("--markdown-playground-url") - .arg("https://play.rust-lang.org/") + .arg("--markdown-playground-url").arg("https://play.rust-lang.org/") .arg("-o").arg(&out) .arg(&path); @@ -523,6 +521,7 @@ impl Step for Std { .arg("--markdown-css").arg("rust.css") .arg("--markdown-no-toc") .arg("--generate-redirect-pages") + .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page").arg(&builder.src.join("src/doc/index.md")); builder.run(&mut cargo); From 2742b23b209eefc2e9962d04990fce0dd51ed552 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 27 Feb 2019 21:01:42 +0000 Subject: [PATCH 09/30] Make migrate mode work at item level granularity --- src/librustc/middle/expr_use_visitor.rs | 8 +++-- src/librustc_borrowck/borrowck/check_loans.rs | 16 ++++++++++ src/librustc_mir/borrow_check/mod.rs | 28 +++------------- ...e-58776-borrowck-scans-children.ast.stderr | 15 +++++++++ ...776-borrowck-scans-children.migrate.stderr | 32 +++++++++++++++++++ ...e-58776-borrowck-scans-children.nll.stderr | 32 +++++++++++++++++++ .../issue-58776-borrowck-scans-children.rs | 21 ++++++++++++ 7 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr create mode 100644 src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr create mode 100644 src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr create mode 100644 src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6e8b661b7b895..9bfb2eb6b26c1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -82,6 +82,9 @@ pub trait Delegate<'tcx> { assignment_span: Span, assignee_cmt: &mc::cmt_<'tcx>, mode: MutateMode); + + // A nested closure or generator - only one layer deep. + fn nested_body(&mut self, _body_id: hir::BodyId) {} } #[derive(Copy, Clone, PartialEq, Debug)] @@ -531,8 +534,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_expr(&base); } - hir::ExprKind::Closure(.., fn_decl_span, _) => { - self.walk_captures(expr, fn_decl_span) + hir::ExprKind::Closure(_, _, body_id, fn_decl_span, _) => { + self.delegate.nested_body(body_id); + self.walk_captures(expr, fn_decl_span); } hir::ExprKind::Box(ref base) => { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index bd854e3aa3c81..4268cb3ea3a4b 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -177,6 +177,22 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { } fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) { } + + fn nested_body(&mut self, body_id: hir::BodyId) { + // rust-lang/rust#58776: MIR and AST borrow check disagree on where + // certain closure errors are reported. As such migrate borrowck has to + // operate at the level of items, rather than bodies. Check if the + // contained closure had any errors and set `signalled_any_error` if it + // has. + let bccx = self.bccx; + if bccx.tcx.migrate_borrowck() { + if let SignalledError::NoErrorsSeen = bccx.signalled_any_error.get() { + let closure_def_id = bccx.tcx.hir().body_owner_def_id(body_id); + + bccx.signalled_any_error.set(bccx.tcx.borrowck(closure_def_id).signalled_any_error); + } + } + } } pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 715ee856a7a62..0515d3e91d316 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -329,30 +329,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // When borrowck=migrate, check if AST-borrowck would // error on the given code. - // rust-lang/rust#55492: loop over parents to ensure that - // errors that AST-borrowck only detects in some parent of - // a closure still allows NLL to signal an error. - let mut curr_def_id = def_id; - let signalled_any_error = loop { - match tcx.borrowck(curr_def_id).signalled_any_error { - SignalledError::NoErrorsSeen => { - // keep traversing (and borrow-checking) parents - } - SignalledError::SawSomeError => { - // stop search here - break SignalledError::SawSomeError; - } - } - - if tcx.is_closure(curr_def_id) { - curr_def_id = tcx.parent_def_id(curr_def_id) - .expect("a closure must have a parent_def_id"); - } else { - break SignalledError::NoErrorsSeen; - } - }; + // rust-lang/rust#55492, rust-lang/rust#58776 check the base def id + // for errors. AST borrowck is responsible for aggregating + // `signalled_any_error` from all of the nested closures here. + let base_def_id = tcx.closure_base_def_id(def_id); - match signalled_any_error { + match tcx.borrowck(base_def_id).signalled_any_error { SignalledError::NoErrorsSeen => { // if AST-borrowck signalled no errors, then // downgrade all the buffered MIR-borrowck errors diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr new file mode 100644 index 0000000000000..9e0b0aac1e3c6 --- /dev/null +++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr @@ -0,0 +1,15 @@ +error[E0597]: `**greeting` does not live long enough + --> $DIR/issue-58776-borrowck-scans-children.rs:10:24 + | +LL | let res = (|| (|| &greeting)())(); + | -- ^^^^^^^^ - borrowed value only lives until here + | | | + | | borrowed value does not live long enough + | capture occurs here +... +LL | } + | - borrowed value needs to live until here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr new file mode 100644 index 0000000000000..bd8f2286f170c --- /dev/null +++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr @@ -0,0 +1,32 @@ +error[E0506]: cannot assign to `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:13:5 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +... +LL | greeting = "DEALLOCATED".to_string(); + | ^^^^^^^^ assignment to borrowed `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error[E0505]: cannot move out of `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:16:10 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +... +LL | drop(greeting); + | ^^^^^^^^ move out of `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error: aborting due to 2 previous errors + +Some errors occurred: E0505, E0506. +For more information about an error, try `rustc --explain E0505`. diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr new file mode 100644 index 0000000000000..bd8f2286f170c --- /dev/null +++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr @@ -0,0 +1,32 @@ +error[E0506]: cannot assign to `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:13:5 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +... +LL | greeting = "DEALLOCATED".to_string(); + | ^^^^^^^^ assignment to borrowed `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error[E0505]: cannot move out of `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:16:10 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +... +LL | drop(greeting); + | ^^^^^^^^ move out of `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error: aborting due to 2 previous errors + +Some errors occurred: E0505, E0506. +For more information about an error, try `rustc --explain E0505`. diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs new file mode 100644 index 0000000000000..378969f9a1867 --- /dev/null +++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs @@ -0,0 +1,21 @@ +// ignore-compare-mode-nll + +// revisions: ast migrate nll + +//[migrate]compile-flags: -Z borrowck=migrate +#![cfg_attr(nll, feature(nll))] + +fn main() { + let mut greeting = "Hello world!".to_string(); + let res = (|| (|| &greeting)())(); + //[ast]~^ ERROR does not live long enough + + greeting = "DEALLOCATED".to_string(); + //[migrate]~^ ERROR cannot assign + //[nll]~^^ ERROR cannot assign + drop(greeting); + //[migrate]~^ ERROR cannot move + //[nll]~^^ ERROR cannot move + + println!("thread result: {:?}", res); +} From e0b37b10c8b4ea3cc36b0f52228afce9a6954e4b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 28 Feb 2019 08:51:35 +0300 Subject: [PATCH 10/30] Add tests for malformed input in `#[proc_macro_derive]` --- src/test/ui/proc-macro/attribute.rs | 94 ++++++++++++-------- src/test/ui/proc-macro/attribute.stderr | 86 ++++++++++++------ src/test/ui/proc-macro/shadow-builtin.rs | 14 --- src/test/ui/proc-macro/shadow-builtin.stderr | 8 -- 4 files changed, 118 insertions(+), 84 deletions(-) delete mode 100644 src/test/ui/proc-macro/shadow-builtin.rs delete mode 100644 src/test/ui/proc-macro/shadow-builtin.stderr diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs index a0b982d75f519..f1775307fb4e5 100644 --- a/src/test/ui/proc-macro/attribute.rs +++ b/src/test/ui/proc-macro/attribute.rs @@ -4,53 +4,73 @@ #![crate_type = "proc-macro"] extern crate proc_macro; +use proc_macro::*; #[proc_macro_derive] //~^ ERROR: attribute must be of the form -pub fn foo1(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +pub fn foo1(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive = "foo"] +#[proc_macro_derive = ""] //~^ ERROR: attribute must be of the form -pub fn foo2(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} - -#[proc_macro_derive( - a = "b" -)] -//~^^ ERROR: must only be one word -pub fn foo3(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} - -#[proc_macro_derive(b, c, d)] +pub fn foo2(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d3, a, b)] +//~^ ERROR: attribute must have either one or two arguments +pub fn foo3(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d4, attributes(a), b)] //~^ ERROR: attribute must have either one or two arguments -pub fn foo4(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +pub fn foo4(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive("a")] +//~^ ERROR: not a meta item +pub fn foo5(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d6 = "")] +//~^ ERROR: must only be one word +pub fn foo6(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(m::d7)] +//FIXME ERROR: must only be one word +pub fn foo7(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(d(e))] +#[proc_macro_derive(d8(a))] //~^ ERROR: must only be one word -pub fn foo5(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +pub fn foo8(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(f, attributes(g = "h"))] +#[proc_macro_derive(self)] +//FIXME ERROR: `self` cannot be a name of derive macro +pub fn foo9(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(PartialEq)] +//~^ ERROR: cannot override a built-in #[derive] mode +pub fn foo10(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d11, a)] +//~^ ERROR: second argument must be `attributes` +//~| ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo11(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d12, attributes)] +//~^ ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo12(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d13, attributes("a"))] +//~^ ERROR: not a meta item +pub fn foo13(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d14, attributes(a = ""))] //~^ ERROR: must only be one word -pub fn foo6(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +pub fn foo14(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d15, attributes(m::a))] +//FIXME ERROR: must only be one word +pub fn foo15(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(i, attributes(j(k)))] +#[proc_macro_derive(d16, attributes(a(b)))] //~^ ERROR: must only be one word -pub fn foo7(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +pub fn foo16(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(l, attributes(m), n)] -//~^ ERROR: attribute must have either one or two arguments -pub fn foo8(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - input -} +#[proc_macro_derive(d17, attributes(self))] +//FIXME ERROR: `self` cannot be a name of derive helper attribute +pub fn foo17(input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr index 231eb1f106898..7bafb0abc4f8a 100644 --- a/src/test/ui/proc-macro/attribute.stderr +++ b/src/test/ui/proc-macro/attribute.stderr @@ -1,50 +1,86 @@ -error: must only be one word - --> $DIR/attribute.rs:21:5 +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:17:1 | -LL | a = "b" - | ^^^^^^^ +LL | #[proc_macro_derive(d3, a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: attribute must have either one or two arguments - --> $DIR/attribute.rs:28:1 + --> $DIR/attribute.rs:21:1 + | +LL | #[proc_macro_derive(d4, attributes(a), b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: not a meta item + --> $DIR/attribute.rs:25:21 | -LL | #[proc_macro_derive(b, c, d)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[proc_macro_derive("a")] + | ^^^ error: must only be one word - --> $DIR/attribute.rs:34:21 + --> $DIR/attribute.rs:29:21 | -LL | #[proc_macro_derive(d(e))] - | ^^^^ +LL | #[proc_macro_derive(d6 = "")] + | ^^^^^^^ error: must only be one word - --> $DIR/attribute.rs:40:35 + --> $DIR/attribute.rs:37:21 + | +LL | #[proc_macro_derive(d8(a))] + | ^^^^^ + +error: cannot override a built-in #[derive] mode + --> $DIR/attribute.rs:45:21 + | +LL | #[proc_macro_derive(PartialEq)] + | ^^^^^^^^^ + +error: second argument must be `attributes` + --> $DIR/attribute.rs:49:26 | -LL | #[proc_macro_derive(f, attributes(g = "h"))] - | ^^^^^^^ +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:49:26 + | +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:54:26 + | +LL | #[proc_macro_derive(d12, attributes)] + | ^^^^^^^^^^ + +error: not a meta item + --> $DIR/attribute.rs:58:37 + | +LL | #[proc_macro_derive(d13, attributes("a"))] + | ^^^ error: must only be one word - --> $DIR/attribute.rs:46:35 + --> $DIR/attribute.rs:62:37 | -LL | #[proc_macro_derive(i, attributes(j(k)))] - | ^^^^ +LL | #[proc_macro_derive(d14, attributes(a = ""))] + | ^^^^^^ -error: attribute must have either one or two arguments - --> $DIR/attribute.rs:52:1 +error: must only be one word + --> $DIR/attribute.rs:70:37 | -LL | #[proc_macro_derive(l, attributes(m), n)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[proc_macro_derive(d16, attributes(a(b)))] + | ^^^^ error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` - --> $DIR/attribute.rs:8:1 + --> $DIR/attribute.rs:9:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` - --> $DIR/attribute.rs:14:1 + --> $DIR/attribute.rs:13:1 | -LL | #[proc_macro_derive = "foo"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[proc_macro_derive = ""] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 14 previous errors diff --git a/src/test/ui/proc-macro/shadow-builtin.rs b/src/test/ui/proc-macro/shadow-builtin.rs deleted file mode 100644 index afcc0ebc3464c..0000000000000 --- a/src/test/ui/proc-macro/shadow-builtin.rs +++ /dev/null @@ -1,14 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_derive(PartialEq)] -//~^ ERROR: cannot override a built-in #[derive] mode -pub fn foo(input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/ui/proc-macro/shadow-builtin.stderr b/src/test/ui/proc-macro/shadow-builtin.stderr deleted file mode 100644 index 668579509dc3b..0000000000000 --- a/src/test/ui/proc-macro/shadow-builtin.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot override a built-in #[derive] mode - --> $DIR/shadow-builtin.rs:10:21 - | -LL | #[proc_macro_derive(PartialEq)] - | ^^^^^^^^^ - -error: aborting due to previous error - From 971542825c8bb23840d8ed00cbf967c1e45be5af Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 28 Feb 2019 09:17:24 +0300 Subject: [PATCH 11/30] syntax: Do not accidentally treat multi-segment meta-items as single-segment --- src/librustc/hir/check_attr.rs | 8 +- src/librustc/ich/impls_syntax.rs | 5 +- src/librustc/lint/levels.rs | 21 +++-- src/librustc/middle/lib_features.rs | 6 +- src/librustc/middle/stability.rs | 11 ++- src/librustc/session/config.rs | 3 +- src/librustc/traits/on_unimplemented.rs | 10 +- src/librustc_incremental/assert_dep_graph.rs | 6 +- .../persist/dirty_clean.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/unused.rs | 8 +- src/librustc_passes/layout_test.rs | 4 +- src/librustc_plugin/load.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 23 +++-- src/librustdoc/clean/cfg.rs | 8 +- src/librustdoc/clean/mod.rs | 6 +- src/librustdoc/core.rs | 3 +- src/librustdoc/html/render.rs | 14 ++- src/librustdoc/visit_ast.rs | 7 +- src/libsyntax/attr/builtin.rs | 94 +++++++++---------- src/libsyntax/attr/mod.rs | 77 +++++++-------- src/libsyntax/ext/tt/macro_rules.rs | 11 ++- src/libsyntax/feature_gate.rs | 33 ++++--- src/libsyntax/test.rs | 5 +- src/libsyntax_ext/deriving/custom.rs | 8 +- src/libsyntax_ext/deriving/generic/mod.rs | 9 +- src/libsyntax_ext/proc_macro_decls.rs | 43 +++++---- src/test/ui/proc-macro/attribute.rs | 4 +- src/test/ui/proc-macro/attribute.stderr | 14 ++- 29 files changed, 236 insertions(+), 213 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 8b304007a3572..a97d7cb869021 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { // ``` let hints: Vec<_> = item.attrs .iter() - .filter(|attr| attr.name() == "repr") + .filter(|attr| attr.check_name("repr")) .filter_map(|attr| attr.meta_item_list()) .flatten() .collect(); @@ -177,7 +177,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { let mut is_transparent = false; for hint in &hints { - let name = if let Some(name) = hint.name() { + let name = if let Some(name) = hint.ident_str() { name } else { // Invalid repr hint like repr(42). We don't check for unrecognized hints here @@ -185,7 +185,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue; }; - let (article, allowed_targets) = match &*name.as_str() { + let (article, allowed_targets) = match name { "C" | "align" => { is_c |= name == "C"; if target != Target::Struct && @@ -313,7 +313,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { fn check_used(&self, item: &hir::Item, target: Target) { for attr in &item.attrs { - if attr.name() == "used" && target != Target::Static { + if attr.check_name("used") && target != Target::Static { self.tcx.sess .span_err(attr.span, "attribute must be applied to a `static` variable"); } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index f34423ccca655..0a1dda7a9cffd 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -197,7 +197,8 @@ impl<'a> HashStable> for [ast::Attribute] { let filtered: SmallVec<[&ast::Attribute; 8]> = self .iter() .filter(|attr| { - !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name()) + !attr.is_sugared_doc && + !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)) }) .collect(); @@ -224,7 +225,7 @@ impl<'a> HashStable> for ast::Attribute { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { // Make sure that these have been filtered out. - debug_assert!(!hcx.is_ignored_attr(self.name())); + debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))); debug_assert!(!self.is_sugared_doc); let ast::Attribute { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 924aa3fde0a08..2430e83122803 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -193,7 +193,7 @@ impl<'a> LintLevelsBuilder<'a> { struct_span_err!(sess, span, E0452, "malformed lint attribute") }; for attr in attrs { - let level = match Level::from_str(&attr.name().as_str()) { + let level = match attr.ident_str().and_then(|name| Level::from_str(name)) { None => continue, Some(lvl) => lvl, }; @@ -254,9 +254,9 @@ impl<'a> LintLevelsBuilder<'a> { } for li in metas { - let word = match li.word() { - Some(word) => word, - None => { + let meta_item = match li.meta_item() { + Some(meta_item) if meta_item.is_word() => meta_item, + _ => { let mut err = bad_attr(li.span); if let Some(item) = li.meta_item() { if let ast::MetaItemKind::NameValue(_) = item.node { @@ -269,23 +269,24 @@ impl<'a> LintLevelsBuilder<'a> { continue; } }; - let tool_name = if let Some(lint_tool) = word.is_scoped() { - if !attr::is_known_lint_tool(lint_tool) { + let tool_name = if meta_item.ident.segments.len() > 1 { + let tool_ident = meta_item.ident.segments[0].ident; + if !attr::is_known_lint_tool(tool_ident) { span_err!( sess, - lint_tool.span, + tool_ident.span, E0710, "an unknown tool name found in scoped lint: `{}`", - word.ident + meta_item.ident ); continue; } - Some(lint_tool.as_str()) + Some(tool_ident.as_str()) } else { None }; - let name = word.name(); + let name = meta_item.ident.segments.last().expect("empty lint name").ident.name; match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span, reason); diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 331343e052dea..3e51f7e0094df 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -63,9 +63,9 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { for meta in metas { if let Some(mi) = meta.meta_item() { // Find the `feature = ".."` meta-item. - match (&*mi.name().as_str(), mi.value_str()) { - ("feature", val) => feature = val, - ("since", val) => since = val, + match (mi.ident_str(), mi.value_str()) { + (Some("feature"), val) => feature = val, + (Some("since"), val) => since = val, _ => {} } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index aa23924486165..8ae54f337056e 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -194,11 +194,12 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } else { // Emit errors for non-staged-api crates. for attr in attrs { - let tag = attr.name(); - if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" { - attr::mark_used(attr); - self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \ - outside of the standard library"); + if let Some(tag) = attr.ident_str() { + if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" { + attr::mark_used(attr); + self.tcx.sess.span_err(attr.span, "stability attributes may not be used \ + outside of the standard library"); + } } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 99eee4b559a5c..662cedbdd01d2 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1817,7 +1817,8 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> ast::CrateConfig { error!("argument value must be a string"); } MetaItemKind::NameValue(..) | MetaItemKind::Word => { - return (meta_item.name(), meta_item.value_str()); + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); } } } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index f61c32614cc93..e6d77f1537cd5 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -177,10 +177,12 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| { - options.contains(&( - c.name().as_str().to_string(), - c.value_str().map(|s| s.as_str().to_string()) - )) + c.ident_str().map_or(false, |name| { + options.contains(&( + name.to_string(), + c.value_str().map(|s| s.as_str().to_string()) + )) + }) }) { debug!("evaluate: skipping {:?} due to condition", command); continue diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 1f69d617c83b7..4d55c5aa0c07b 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -99,9 +99,9 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { fn argument(&self, attr: &ast::Attribute) -> Option { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { - match list_item.word() { - Some(word) if value.is_none() => - value = Some(word.name()), + match list_item.ident() { + Some(ident) if list_item.is_word() && value.is_none() => + value = Some(ident.name), _ => // FIXME better-encapsulate meta_item (don't directly access `node`) span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node), diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 2794b6c556ff2..eff502a26425e 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -576,7 +576,7 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as if let Some(value) = item.value_str() { value } else { - let msg = if let Some(name) = item.name() { + let msg = if let Some(name) = item.ident_str() { format!("associated value expected for `{}`", name) } else { "expected an associated value".to_string() diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 641adec82cdd9..cefb97946aba8 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -760,7 +760,7 @@ impl LintPass for DeprecatedAttr { impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { for &&(n, _, _, ref g) in &self.depr_attrs { - if attr.name() == n { + if attr.ident_str() == Some(n) { if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion), ref name, ref reason, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 86b8b276eafe5..743866d8507bf 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -267,19 +267,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { } } - let name = attr.name(); + let name = attr.ident_str(); if !attr::is_used(attr) { debug!("Emitting warning for: {:?}", attr); cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); // Is it a builtin attribute that must be used at the crate level? let known_crate = BUILTIN_ATTRIBUTES.iter() - .find(|&&(builtin, ty, ..)| name == builtin && ty == AttributeType::CrateLevel) + .find(|&&(builtin, ty, ..)| { + name == Some(builtin) && ty == AttributeType::CrateLevel + }) .is_some(); // Has a plugin registered this attribute as one that must be used at // the crate level? let plugin_crate = plugin_attributes.iter() - .find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t) + .find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t) .is_some(); if known_crate || plugin_crate { let msg = match attr.style { diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index 7fe3f5a36d850..e2a74f5c4285b 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -53,9 +53,7 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> { // The `..` are the names of fields to dump. let meta_items = attr.meta_item_list().unwrap_or_default(); for meta_item in meta_items { - let name = meta_item.word().map(|mi| mi.name().as_str()); - let name = name.as_ref().map(|s| &s[..]).unwrap_or(""); - + let name = meta_item.ident_str().unwrap_or(""); match name { "abi" => { self.tcx diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 1b88cf05f40d5..2f4332e71237d 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -56,10 +56,10 @@ pub fn load_plugins(sess: &Session, for plugin in plugins { // plugins must have a name and can't be key = value - match plugin.name() { + match plugin.ident_str() { Some(name) if !plugin.is_value_str() => { let args = plugin.meta_item_list().map(ToOwned::to_owned); - loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default()); + loader.load_plugin(plugin.span, name, args.unwrap_or_default()); }, _ => call_malformed_plugin_attribute(sess, attr.span), } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 29de5308a3cdb..174a921f0f398 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -466,10 +466,9 @@ impl<'a> Resolver<'a> { if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") { if let Some(trait_attr) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) { - if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) { - let sp = trait_attr.span; + if let Some(ident) = trait_attr.ident() { let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub); - self.define(parent, ident, MacroNS, (def, vis, sp, expansion)); + self.define(parent, ident, MacroNS, (def, vis, ident.span, expansion)); } } } @@ -815,9 +814,9 @@ impl<'a> Resolver<'a> { break; } MetaItemKind::List(nested_metas) => for nested_meta in nested_metas { - match nested_meta.word() { - Some(word) => single_imports.push((word.name(), word.span)), - None => ill_formed(nested_meta.span), + match nested_meta.ident() { + Some(ident) if nested_meta.is_word() => single_imports.push(ident), + _ => ill_formed(nested_meta.span), } } MetaItemKind::NameValue(..) => ill_formed(meta.span), @@ -853,23 +852,23 @@ impl<'a> Resolver<'a> { self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); }); } else { - for (name, span) in single_imports.iter().cloned() { - let ident = Ident::with_empty_ctxt(name); + for ident in single_imports.iter().cloned() { let result = self.resolve_ident_in_module( ModuleOrUniformRoot::Module(module), ident, MacroNS, None, false, - span, + ident.span, ); if let Ok(binding) = result { - let directive = macro_use_directive(span); + let directive = macro_use_directive(ident.span); self.potentially_unused_imports.push(directive); let imported_binding = self.import(binding, directive); - self.legacy_import_macro(name, imported_binding, span, allow_shadowing); + self.legacy_import_macro(ident.name, imported_binding, + ident.span, allow_shadowing); } else { - span_err!(self.session, span, E0469, "imported macro not found"); + span_err!(self.session, ident.span, E0469, "imported macro not found"); } } } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 45e1ea2d3a39d..7ebcf2cbd912c 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -58,7 +58,13 @@ impl Cfg { /// If the content is not properly formatted, it will return an error indicating what and where /// the error is. pub fn parse(cfg: &MetaItem) -> Result { - let name = cfg.name(); + let name = match cfg.ident() { + Some(ident) => ident.name, + None => return Err(InvalidCfgError { + msg: "expected a single identifier", + span: cfg.span + }), + }; match cfg.node { MetaItemKind::Word => Ok(Cfg::Cfg(name, None)), MetaItemKind::NameValue(ref lit) => match lit.node { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c64a73fa308e1..929d8404a8ce8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -491,7 +491,7 @@ impl Item { pub fn is_non_exhaustive(&self) -> bool { self.attrs.other_attrs.iter() - .any(|a| a.name().as_str() == "non_exhaustive") + .any(|a| a.check_name("non_exhaustive")) } /// Returns a documentation-level item type from the item. @@ -3673,7 +3673,7 @@ impl Clean> for doctree::ExternCrate { fn clean(&self, cx: &DocContext<'_, '_, '_>) -> Vec { let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| { - a.name() == "doc" && match a.meta_item_list() { + a.check_name("doc") && match a.meta_item_list() { Some(l) => attr::list_contains_name(&l, "inline"), None => false, } @@ -3712,7 +3712,7 @@ impl Clean> for doctree::Import { // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { - a.name() == "doc" && match a.meta_item_list() { + a.check_name("doc") && match a.meta_item_list() { Some(l) => attr::list_contains_name(&l, "no_inline") || attr::list_contains_name(&l, "hidden"), None => false, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index fdb071638b799..8727c12cc0f85 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -565,8 +565,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt for attr in krate.module.as_ref().unwrap().attrs.lists("doc") { let diag = ctxt.sess().diagnostic(); - let name = attr.name().map(|s| s.as_str()); - let name = name.as_ref().map(|s| &s[..]); + let name = attr.ident_str(); if attr.is_word() { if name == Some("no_default_passes") { report_deprecated_attr("no_default_passes", diag); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d711e4514a049..7f6a1df6ff928 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -562,8 +562,7 @@ pub fn run(mut krate: clean::Crate, // going to emit HTML if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) { for attr in attrs.lists("doc") { - let name = attr.name().map(|s| s.as_str()); - match (name.as_ref().map(|s| &s[..]), attr.value_str()) { + match (attr.ident_str(), attr.value_str()) { (Some("html_favicon_url"), Some(s)) => { scx.layout.favicon = s.to_string(); } @@ -3718,19 +3717,19 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, } fn render_attribute(attr: &ast::MetaItem) -> Option { - let name = attr.name(); + let path = attr.ident.to_string(); if attr.is_word() { - Some(name.to_string()) + Some(path) } else if let Some(v) = attr.value_str() { - Some(format!("{} = {:?}", name, v.as_str())) + Some(format!("{} = {:?}", path, v.as_str())) } else if let Some(values) = attr.meta_item_list() { let display: Vec<_> = values.iter().filter_map(|attr| { attr.meta_item().and_then(|mi| render_attribute(mi)) }).collect(); if display.len() > 0 { - Some(format!("{}({})", name, display.join(", "))) + Some(format!("{}({})", path, display.join(", "))) } else { None } @@ -3754,8 +3753,7 @@ fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Resul let mut attrs = String::new(); for attr in &it.attrs.other_attrs { - let name = attr.name(); - if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) { + if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) { continue; } if let Some(s) = render_attribute(&attr.meta().unwrap()) { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c1bd1d83a5b00..f5c29867d5bfa 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -178,9 +178,10 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { Some(kind) => { let name = if kind == MacroKind::Derive { item.attrs.lists("proc_macro_derive") - .filter_map(|mi| mi.name()) + .filter_map(|mi| mi.ident()) .next() .expect("proc-macro derives require a name") + .name } else { name }; @@ -193,8 +194,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { if let Some(list) = mi.meta_item_list() { for inner_mi in list { - if let Some(name) = inner_mi.name() { - helpers.push(name); + if let Some(ident) = inner_mi.ident() { + helpers.push(ident.name); } } } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index e84adc01cf04a..d97f817931077 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -1,6 +1,6 @@ //! Parsing and validation of builtin attributes -use crate::ast::{self, Attribute, MetaItem, Name, NestedMetaItemKind}; +use crate::ast::{self, Attribute, MetaItem, NestedMetaItemKind}; use crate::feature_gate::{Features, GatedCfg}; use crate::parse::ParseSess; @@ -10,8 +10,8 @@ use syntax_pos::{symbol::Symbol, Span}; use super::{list_contains_name, mark_used, MetaItemKind}; enum AttrError { - MultipleItem(Name), - UnknownMetaItem(Name, &'static [&'static str]), + MultipleItem(String), + UnknownMetaItem(String, &'static [&'static str]), MissingSince, MissingFeature, MultipleStabilityLevels, @@ -169,10 +169,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { attrs.iter().any(|item| { item.check_name("feature") && item.meta_item_list().map(|list| { - list.iter().any(|mi| { - mi.word().map(|w| w.name() == feature_name) - .unwrap_or(false) - }) + list.iter().any(|mi| mi.is_word() && mi.check_name(feature_name)) }).unwrap_or(false) }) } @@ -220,7 +217,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.ident.to_string())); return false } if let Some(v) = meta.value_str() { @@ -239,9 +236,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, )+ for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name().as_str() { + match mi.ident_str() { $( - stringify!($name) + Some(stringify!($name)) => if !get(mi, &mut $name) { continue 'outer }, )+ _ => { @@ -249,7 +246,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, handle_errors( sess, mi.span, - AttrError::UnknownMetaItem(mi.name(), expected), + AttrError::UnknownMetaItem(mi.ident.to_string(), expected), ); continue 'outer } @@ -269,7 +266,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } } - match &*meta.name().as_str() { + match meta.ident_str().expect("not a stability level") { "rustc_deprecated" => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, @@ -323,16 +320,16 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let mut issue = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name().as_str() { - "feature" => if !get(mi, &mut feature) { continue 'outer }, - "reason" => if !get(mi, &mut reason) { continue 'outer }, - "issue" => if !get(mi, &mut issue) { continue 'outer }, + match mi.ident_str() { + Some("feature") => if !get(mi, &mut feature) { continue 'outer }, + Some("reason") => if !get(mi, &mut reason) { continue 'outer }, + Some("issue") => if !get(mi, &mut issue) { continue 'outer }, _ => { handle_errors( sess, meta.span, AttrError::UnknownMetaItem( - mi.name(), + mi.ident.to_string(), &["feature", "reason", "issue"] ), ); @@ -394,15 +391,17 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, for meta in metas { match &meta.node { NestedMetaItemKind::MetaItem(mi) => { - match &*mi.name().as_str() { - "feature" => if !get(mi, &mut feature) { continue 'outer }, - "since" => if !get(mi, &mut since) { continue 'outer }, + match mi.ident_str() { + Some("feature") => + if !get(mi, &mut feature) { continue 'outer }, + Some("since") => + if !get(mi, &mut since) { continue 'outer }, _ => { handle_errors( sess, meta.span, AttrError::UnknownMetaItem( - mi.name(), &["since", "note"], + mi.ident.to_string(), &["since", "note"], ), ); continue 'outer @@ -516,7 +515,8 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat true } MetaItemKind::NameValue(..) | MetaItemKind::Word => { - sess.config.contains(&(cfg.name(), cfg.value_str())) + let ident = cfg.ident().expect("multi-segment cfg predicate"); + sess.config.contains(&(ident.name, cfg.value_str())) } } }) @@ -546,14 +546,14 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) // The unwraps below may look dangerous, but we've already asserted // that they won't fail with the loop above. - match &*cfg.name().as_str() { - "any" => mis.iter().any(|mi| { + match cfg.ident_str() { + Some("any") => mis.iter().any(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), - "all" => mis.iter().all(|mi| { + Some("all") => mis.iter().all(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), - "not" => { + Some("not") => { if mis.len() != 1 { span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern"); return false; @@ -561,8 +561,9 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) !eval_condition(mis[0].meta_item().unwrap(), sess, eval) }, - p => { - span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p); + _ => { + span_err!(sess.span_diagnostic, cfg.span, E0537, + "invalid predicate `{}`", cfg.ident); false } } @@ -616,7 +617,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, MetaItemKind::List(list) => { let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); + handle_errors( + sess, meta.span, AttrError::MultipleItem(meta.ident.to_string()) + ); return false } if let Some(v) = meta.value_str() { @@ -646,14 +649,15 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, for meta in list { match &meta.node { NestedMetaItemKind::MetaItem(mi) => { - match &*mi.name().as_str() { - "since" => if !get(mi, &mut since) { continue 'outer }, - "note" => if !get(mi, &mut note) { continue 'outer }, + match mi.ident_str() { + Some("since") => if !get(mi, &mut since) { continue 'outer }, + Some("note") => if !get(mi, &mut note) { continue 'outer }, _ => { handle_errors( sess, - meta.span, - AttrError::UnknownMetaItem(mi.name(), &["since", "note"]), + meta.span(), + AttrError::UnknownMetaItem(mi.ident.to_string(), + &["since", "note"]), ); continue 'outer } @@ -738,19 +742,13 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { } let mut recognised = false; - if let Some(mi) = item.word() { - let word = &*mi.name().as_str(); - let hint = match word { - "C" => Some(ReprC), - "packed" => Some(ReprPacked(1)), - "simd" => Some(ReprSimd), - "transparent" => Some(ReprTransparent), - _ => match int_type_of_word(word) { - Some(ity) => Some(ReprInt(ity)), - None => { - None - } - } + if item.is_word() { + let hint = match item.ident_str() { + Some("C") => Some(ReprC), + Some("packed") => Some(ReprPacked(1)), + Some("simd") => Some(ReprSimd), + Some("transparent") => Some(ReprTransparent), + name => name.and_then(|name| int_type_of_word(name)).map(ReprInt), }; if let Some(h) = hint { @@ -796,7 +794,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { } } else { if let Some(meta_item) = item.meta_item() { - if meta_item.name() == "align" { + if meta_item.check_name("align") { if let MetaItemKind::NameValue(ref value) = meta_item.node { recognised = true; let mut err = struct_span_err!(diagnostic, item.span, E0693, diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index b5fc850731404..857325681c660 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -90,10 +90,12 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// Returns the name of the meta item, e.g., `foo` in `#[foo]`, - /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem - pub fn name(&self) -> Option { - self.meta_item().and_then(|meta_item| Some(meta_item.name())) + /// For a single-segment meta-item returns its name, otherwise returns `None`. + pub fn ident(&self) -> Option { + self.meta_item().and_then(|meta_item| meta_item.ident()) + } + pub fn ident_str(&self) -> Option<&str> { + self.ident().map(|name| name.as_str().get()) } /// Gets the string value if self is a MetaItem and the MetaItem is a @@ -108,25 +110,14 @@ impl NestedMetaItem { |meta_item| meta_item.meta_item_list().and_then( |meta_item_list| { if meta_item_list.len() == 1 { - let nested_item = &meta_item_list[0]; - if nested_item.is_literal() { - Some((meta_item.name(), nested_item.literal().unwrap())) - } else { - None + if let Some(ident) = meta_item.ident() { + if let Some(lit) = meta_item_list[0].literal() { + return Some((ident.name, lit)); + } } } - else { - None - }})) - } - - /// Returns a MetaItem if self is a MetaItem with Kind Word. - pub fn word(&self) -> Option<&MetaItem> { - self.meta_item().and_then(|meta_item| if meta_item.is_word() { - Some(meta_item) - } else { - None - }) + None + })) } /// Gets a list of inner meta items from a list MetaItem type. @@ -146,7 +137,7 @@ impl NestedMetaItem { /// Returns `true` if self is a MetaItem and the meta item is a word. pub fn is_word(&self) -> bool { - self.word().is_some() + self.meta_item().map_or(false, |meta_item| meta_item.is_word()) } /// Returns `true` if self is a MetaItem and the meta item is a ValueString. @@ -160,10 +151,6 @@ impl NestedMetaItem { } } -fn name_from_path(path: &Path) -> Name { - path.segments.last().expect("empty path in attribute").ident.name -} - impl Attribute { /// Returns `true` if the attribute's path matches the argument. If it matches, then the /// attribute is marked as used. @@ -177,10 +164,16 @@ impl Attribute { matches } - /// Returns the **last** segment of the name of this attribute. - /// e.g., `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`. - pub fn name(&self) -> Name { - name_from_path(&self.path) + /// For a single-segment attribute returns its name, otherwise returns `None`. + pub fn ident(&self) -> Option { + if self.path.segments.len() == 1 { + Some(self.path.segments[0].ident) + } else { + None + } + } + pub fn ident_str(&self) -> Option<&str> { + self.ident().map(|name| name.as_str().get()) } pub fn value_str(&self) -> Option { @@ -195,7 +188,7 @@ impl Attribute { } pub fn is_word(&self) -> bool { - self.path.segments.len() == 1 && self.tokens.is_empty() + self.tokens.is_empty() } pub fn span(&self) -> Span { @@ -213,8 +206,16 @@ impl Attribute { } impl MetaItem { - pub fn name(&self) -> Name { - name_from_path(&self.ident) + /// For a single-segment meta-item returns its name, otherwise returns `None`. + pub fn ident(&self) -> Option { + if self.ident.segments.len() == 1 { + Some(self.ident.segments[0].ident) + } else { + None + } + } + pub fn ident_str(&self) -> Option<&str> { + self.ident().map(|name| name.as_str().get()) } // #[attribute(name = "value")] @@ -255,7 +256,7 @@ impl MetaItem { pub fn span(&self) -> Span { self.span } pub fn check_name(&self, name: &str) -> bool { - self.name() == name + self.ident == name } pub fn is_value_str(&self) -> bool { @@ -265,14 +266,6 @@ impl MetaItem { pub fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() } - - pub fn is_scoped(&self) -> Option { - if self.ident.segments.len() > 1 { - Some(self.ident.segments[0].ident) - } else { - None - } - } } impl Attribute { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index bd64bb010219b..12912044e4e3d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -380,9 +380,14 @@ pub fn compile( .map(|attr| attr .meta_item_list() .map(|list| list.iter() - .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( - it.span, "allow internal unstable expects feature names", - ))) + .filter_map(|it| { + let name = it.ident().map(|ident| ident.name); + if name.is_none() { + sess.span_diagnostic.span_err(it.span(), + "allow internal unstable expects feature names") + } + name + }) .collect::>().into() ) .unwrap_or_else(|| { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1c0b931b289c2..b8281b3bf58f2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1289,9 +1289,8 @@ pub struct GatedCfg { impl GatedCfg { pub fn gate(cfg: &ast::MetaItem) -> Option { - let name = cfg.name().as_str(); GATED_CFGS.iter() - .position(|info| info.0 == name) + .position(|info| cfg.check_name(info.0)) .map(|idx| { GatedCfg { span: cfg.span, @@ -1342,16 +1341,16 @@ macro_rules! gate_feature { impl<'a> Context<'a> { fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) { debug!("check_attribute(attr = {:?})", attr); - let name = attr.name().as_str(); + let name = attr.ident_str(); for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES { - if name == n { + if name == Some(n) { if let Gated(_, name, desc, ref has_feature) = *gateage { if !attr.span.allows_unstable(name) { gate_feature_fn!( self, has_feature, attr.span, name, desc, GateStrength::Hard ); } - } else if name == "doc" { + } else if n == "doc" { if let Some(content) = attr.meta_item_list() { if content.iter().any(|c| c.check_name("include")) { gate_feature!(self, external_doc, attr.span, @@ -1374,7 +1373,7 @@ impl<'a> Context<'a> { } } if !attr::is_known(attr) { - if name.starts_with("rustc_") { + if name.map_or(false, |name| name.starts_with("rustc_")) { let msg = "unless otherwise specified, attributes with the prefix `rustc_` \ are reserved for internal compiler diagnostics"; gate_feature!(self, rustc_attrs, attr.span, msg); @@ -2055,13 +2054,12 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], }; for mi in list { - let name = if let Some(word) = mi.word() { - word.name() - } else { - continue + let name = match mi.ident_str() { + Some(name) if mi.is_word() => name, + _ => continue, }; - if incomplete_features.iter().any(|f| *f == name.as_str()) { + if incomplete_features.iter().any(|f| *f == name) { span_handler.struct_span_warn( mi.span, &format!( @@ -2101,12 +2099,13 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], }; for mi in list { - let name = if let Some(word) = mi.word() { - word.name() - } else { - span_err!(span_handler, mi.span, E0556, - "malformed feature, expected just one word"); - continue + let name = match mi.ident() { + Some(ident) if mi.is_word() => ident.name, + _ => { + span_err!(span_handler, mi.span, E0556, + "malformed feature, expected just one word"); + continue + } }; if let Some(edition) = edition_enabled_features.get(&name) { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 56290fa771ba9..3afd55899c8f6 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -438,6 +438,9 @@ fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option meta_item.ident.clone(), + _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise() + } }) } diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index cfc3c931598a1..e73110717e979 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -17,9 +17,11 @@ struct MarkAttrs<'a>(&'a [ast::Name]); impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - if self.0.contains(&attr.name()) { - mark_used(attr); - mark_known(attr); + if let Some(ident) = attr.ident() { + if self.0.contains(&ident.name) { + mark_used(attr); + mark_known(attr); + } } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index b8f96c5bc0ea9..2bb98c1bf625c 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -463,12 +463,9 @@ impl<'a> TraitDef<'a> { let mut attrs = newitem.attrs.clone(); attrs.extend(item.attrs .iter() - .filter(|a| { - match &*a.name().as_str() { - "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true, - _ => false, - } - }) + .filter(|a| a.ident_str().map_or(false, |name| { + ["allow", "warn", "deny", "forbid", "stable", "unstable"].contains(&name) + })) .cloned()); push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) } diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index d8f8decef39b1..4cd42d6d755ed 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -113,24 +113,27 @@ impl<'a> CollectProcMacros<'a> { "attribute must have either one or two arguments"); return } - let trait_attr = &list[0]; - let attributes_attr = list.get(1); - let trait_name = match trait_attr.name() { - Some(name) => name, + let trait_attr = match list[0].meta_item() { + Some(meta_item) => meta_item, _ => { - self.handler.span_err(trait_attr.span(), "not a meta item"); + self.handler.span_err(list[0].span(), "not a meta item"); + return + } + }; + let trait_ident = match trait_attr.ident() { + Some(trait_ident) if trait_attr.is_word() => trait_ident, + _ => { + self.handler.span_err(trait_attr.span, "must only be one word"); return } }; - if !trait_attr.is_word() { - self.handler.span_err(trait_attr.span(), "must only be one word"); - } - if deriving::is_builtin_trait(trait_name) { - self.handler.span_err(trait_attr.span(), + if deriving::is_builtin_trait(trait_ident.name) { + self.handler.span_err(trait_attr.span, "cannot override a built-in #[derive] mode"); } + let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { if !attr.check_name("attributes") { self.handler.span_err(attr.span(), "second argument must be `attributes`") @@ -141,20 +144,22 @@ impl<'a> CollectProcMacros<'a> { `attributes(foo, bar)`"); &[] }).into_iter().filter_map(|attr| { - let name = match attr.name() { - Some(name) => name, + let attr = match attr.meta_item() { + Some(meta_item) => meta_item, _ => { self.handler.span_err(attr.span(), "not a meta item"); return None; }, }; - if !attr.is_word() { - self.handler.span_err(attr.span(), "must only be one word"); - return None; - } - - Some(name) + let ident = match attr.ident() { + Some(ident) if attr.is_word() => ident, + _ => { + self.handler.span_err(attr.span, "must only be one word"); + return None; + } + }; + Some(ident.name) }).collect() } else { Vec::new() @@ -163,7 +168,7 @@ impl<'a> CollectProcMacros<'a> { if self.in_root && item.vis.node.is_pub() { self.derives.push(ProcMacroDerive { span: item.span, - trait_name, + trait_name: trait_ident.name, function_name: item.ident, attrs: proc_attrs, }); diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs index f1775307fb4e5..750f63f9b6b1b 100644 --- a/src/test/ui/proc-macro/attribute.rs +++ b/src/test/ui/proc-macro/attribute.rs @@ -31,7 +31,7 @@ pub fn foo5(input: TokenStream) -> TokenStream { input } pub fn foo6(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(m::d7)] -//FIXME ERROR: must only be one word +//~^ ERROR: must only be one word pub fn foo7(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d8(a))] @@ -64,7 +64,7 @@ pub fn foo13(input: TokenStream) -> TokenStream { input } pub fn foo14(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d15, attributes(m::a))] -//FIXME ERROR: must only be one word +//~^ ERROR: must only be one word pub fn foo15(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d16, attributes(a(b)))] diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr index 7bafb0abc4f8a..a1b3a4aaf2923 100644 --- a/src/test/ui/proc-macro/attribute.stderr +++ b/src/test/ui/proc-macro/attribute.stderr @@ -22,6 +22,12 @@ error: must only be one word LL | #[proc_macro_derive(d6 = "")] | ^^^^^^^ +error: must only be one word + --> $DIR/attribute.rs:33:21 + | +LL | #[proc_macro_derive(m::d7)] + | ^^^^^ + error: must only be one word --> $DIR/attribute.rs:37:21 | @@ -64,6 +70,12 @@ error: must only be one word LL | #[proc_macro_derive(d14, attributes(a = ""))] | ^^^^^^ +error: must only be one word + --> $DIR/attribute.rs:66:37 + | +LL | #[proc_macro_derive(d15, attributes(m::a))] + | ^^^^ + error: must only be one word --> $DIR/attribute.rs:70:37 | @@ -82,5 +94,5 @@ error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ att LL | #[proc_macro_derive = ""] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 16 previous errors From cd71788b8cbc55eb89a391eb65bcc6cb27c5a107 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 3 Mar 2019 19:04:58 +0300 Subject: [PATCH 12/30] syntax_ext: Validate `#[proc_macro_derive]` input better Tweak some error wording --- src/libsyntax/ext/expand.rs | 4 ++-- src/libsyntax_ext/proc_macro_decls.rs | 18 ++++++++++++++---- src/test/ui/proc-macro/attribute.rs | 6 +++--- src/test/ui/proc-macro/attribute.stderr | 16 ++++++++++++++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b805213bb1a4c..46342e162cf9b 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -601,7 +601,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { res } ProcMacroDerive(..) | BuiltinDerive(..) => { - self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path)); + self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path)); self.cx.trace_macros_diag(); invoc.fragment_kind.dummy(attr.span) } @@ -822,7 +822,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } ProcMacroDerive(..) | BuiltinDerive(..) => { - self.cx.span_err(path.span, &format!("`{}` is a derive mode", path)); + self.cx.span_err(path.span, &format!("`{}` is a derive macro", path)); self.cx.trace_macros_diag(); kind.dummy(span) } diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 4cd42d6d755ed..efa6ce56648eb 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -128,9 +128,13 @@ impl<'a> CollectProcMacros<'a> { } }; + if trait_ident.is_path_segment_keyword() { + self.handler.span_err(trait_attr.span(), + &format!("`{}` cannot be a name of derive macro", trait_ident)); + } if deriving::is_builtin_trait(trait_ident.name) { self.handler.span_err(trait_attr.span, - "cannot override a built-in #[derive] mode"); + "cannot override a built-in derive macro"); } let attributes_attr = list.get(1); @@ -140,8 +144,7 @@ impl<'a> CollectProcMacros<'a> { } attr.meta_item_list().unwrap_or_else(|| { self.handler.span_err(attr.span(), - "attribute must be of form: \ - `attributes(foo, bar)`"); + "attribute must be of form: `attributes(foo, bar)`"); &[] }).into_iter().filter_map(|attr| { let attr = match attr.meta_item() { @@ -149,7 +152,7 @@ impl<'a> CollectProcMacros<'a> { _ => { self.handler.span_err(attr.span(), "not a meta item"); return None; - }, + } }; let ident = match attr.ident() { @@ -159,6 +162,13 @@ impl<'a> CollectProcMacros<'a> { return None; } }; + if ident.is_path_segment_keyword() { + self.handler.span_err( + attr.span(), + &format!("`{}` cannot be a name of derive helper attribute", ident), + ); + } + Some(ident.name) }).collect() } else { diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs index 750f63f9b6b1b..ac7d0b4c2b6c9 100644 --- a/src/test/ui/proc-macro/attribute.rs +++ b/src/test/ui/proc-macro/attribute.rs @@ -39,11 +39,11 @@ pub fn foo7(input: TokenStream) -> TokenStream { input } pub fn foo8(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(self)] -//FIXME ERROR: `self` cannot be a name of derive macro +//~^ ERROR: `self` cannot be a name of derive macro pub fn foo9(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(PartialEq)] -//~^ ERROR: cannot override a built-in #[derive] mode +//~^ ERROR: cannot override a built-in derive macro pub fn foo10(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d11, a)] @@ -72,5 +72,5 @@ pub fn foo15(input: TokenStream) -> TokenStream { input } pub fn foo16(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d17, attributes(self))] -//FIXME ERROR: `self` cannot be a name of derive helper attribute +//~^ ERROR: `self` cannot be a name of derive helper attribute pub fn foo17(input: TokenStream) -> TokenStream { input } diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr index a1b3a4aaf2923..cc17d383569fc 100644 --- a/src/test/ui/proc-macro/attribute.stderr +++ b/src/test/ui/proc-macro/attribute.stderr @@ -34,7 +34,13 @@ error: must only be one word LL | #[proc_macro_derive(d8(a))] | ^^^^^ -error: cannot override a built-in #[derive] mode +error: `self` cannot be a name of derive macro + --> $DIR/attribute.rs:41:21 + | +LL | #[proc_macro_derive(self)] + | ^^^^ + +error: cannot override a built-in derive macro --> $DIR/attribute.rs:45:21 | LL | #[proc_macro_derive(PartialEq)] @@ -82,6 +88,12 @@ error: must only be one word LL | #[proc_macro_derive(d16, attributes(a(b)))] | ^^^^ +error: `self` cannot be a name of derive helper attribute + --> $DIR/attribute.rs:74:37 + | +LL | #[proc_macro_derive(d17, attributes(self))] + | ^^^^ + error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` --> $DIR/attribute.rs:9:1 | @@ -94,5 +106,5 @@ error: attribute must be of the form `#[proc_macro_derive(TraitName, /*opt*/ att LL | #[proc_macro_derive = ""] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 16 previous errors +error: aborting due to 18 previous errors From 37e7ae17522282fbb1ae7c236a14742e33a94604 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 27 Feb 2019 22:06:26 +0300 Subject: [PATCH 13/30] syntax: Introduce `Ident::can_be_raw` --- src/libsyntax/parse/lexer/mod.rs | 12 ++++-------- src/libsyntax/parse/parser.rs | 4 +--- src/libsyntax_ext/proc_macro_decls.rs | 4 ++-- src/libsyntax_ext/proc_macro_server.rs | 8 ++------ src/libsyntax_pos/symbol.rs | 13 +++++++++---- src/test/ui/parser/raw/raw-literal-self.rs | 5 +++-- src/test/ui/parser/raw/raw-literal-self.stderr | 8 ++++---- src/test/ui/parser/raw/raw-literal-underscore.rs | 5 +++-- .../ui/parser/raw/raw-literal-underscore.stderr | 8 ++++---- src/test/ui/proc-macro/invalid-punct-ident-3.stderr | 2 +- 10 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index a7cde5fbb92cd..19c0513268a3c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1,7 +1,7 @@ use crate::ast::{self, Ident}; use crate::source_map::{SourceMap, FilePathMapping}; use crate::parse::{token, ParseSess}; -use crate::symbol::{Symbol, keywords}; +use crate::symbol::Symbol; use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder}; use syntax_pos::{BytePos, CharPos, Pos, Span, NO_EXPANSION}; @@ -1249,15 +1249,11 @@ impl<'a> StringReader<'a> { // FIXME: perform NFKC normalization here. (Issue #2253) let ident = self.mk_ident(string); - if is_raw_ident && (ident.is_path_segment_keyword() || - ident.name == keywords::Underscore.name()) { - self.fatal_span_(raw_start, self.pos, - &format!("`r#{}` is not currently supported.", ident.name) - ).raise(); - } - if is_raw_ident { let span = self.mk_sp(raw_start, self.pos); + if !ident.can_be_raw() { + self.err_span(span, &format!("`{}` cannot be a raw identifier", ident)); + } self.sess.raw_identifier_spans.borrow_mut().push(span); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fd5038a8614f2..bb13077627491 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -884,9 +884,7 @@ impl<'a> Parser<'a> { &format!("expected identifier, found {}", self.this_token_descr())); if let token::Ident(ident, false) = &self.token { - if ident.is_reserved() && !ident.is_path_segment_keyword() && - ident.name != keywords::Underscore.name() - { + if ident.is_raw_guess() { err.span_suggestion( self.span, "you can escape reserved keywords to use them as identifiers", diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index efa6ce56648eb..6787ba6dd4390 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -128,7 +128,7 @@ impl<'a> CollectProcMacros<'a> { } }; - if trait_ident.is_path_segment_keyword() { + if !trait_ident.can_be_raw() { self.handler.span_err(trait_attr.span(), &format!("`{}` cannot be a name of derive macro", trait_ident)); } @@ -162,7 +162,7 @@ impl<'a> CollectProcMacros<'a> { return None; } }; - if ident.is_path_segment_keyword() { + if !ident.can_be_raw() { self.handler.span_err( attr.span(), &format!("`{}` cannot be a name of derive helper attribute", ident), diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index 4c4b33c04422b..40ba94e928a3c 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -341,12 +341,8 @@ impl Ident { if !Self::is_valid(string) { panic!("`{:?}` is not a valid identifier", string) } - if is_raw { - let normalized_sym = Symbol::intern(string); - if normalized_sym == keywords::Underscore.name() || - ast::Ident::with_empty_ctxt(normalized_sym).is_path_segment_keyword() { - panic!("`{:?}` is not a valid raw identifier", string) - } + if is_raw && !ast::Ident::from_str(string).can_be_raw() { + panic!("`{}` cannot be a raw identifier", string); } Ident { sym, is_raw, span } } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c5301f9f174c0..e8d215a562e2c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -484,11 +484,16 @@ impl Ident { self.name == keywords::DollarCrate.name() } - // We see this identifier in a normal identifier position, like variable name or a type. - // How was it written originally? Did it use the raw form? Let's try to guess. - pub fn is_raw_guess(self) -> bool { + /// This identifier can be a raw identifier. + pub fn can_be_raw(self) -> bool { self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() && - self.is_reserved() && !self.is_path_segment_keyword() + !self.is_path_segment_keyword() + } + + /// We see this identifier in a normal identifier position, like variable name or a type. + /// How was it written originally? Did it use the raw form? Let's try to guess. + pub fn is_raw_guess(self) -> bool { + self.can_be_raw() && self.is_reserved() } } diff --git a/src/test/ui/parser/raw/raw-literal-self.rs b/src/test/ui/parser/raw/raw-literal-self.rs index d7b9553d032d3..123a11b6f8543 100644 --- a/src/test/ui/parser/raw/raw-literal-self.rs +++ b/src/test/ui/parser/raw/raw-literal-self.rs @@ -1,3 +1,4 @@ -fn self_test(r#self: u32) { - //~^ ERROR `r#self` is not currently supported. +fn main() { + let r#self; + //~^ ERROR `self` cannot be a raw identifier } diff --git a/src/test/ui/parser/raw/raw-literal-self.stderr b/src/test/ui/parser/raw/raw-literal-self.stderr index e64332785cc51..9a330fcdf2aae 100644 --- a/src/test/ui/parser/raw/raw-literal-self.stderr +++ b/src/test/ui/parser/raw/raw-literal-self.stderr @@ -1,8 +1,8 @@ -error: `r#self` is not currently supported. - --> $DIR/raw-literal-self.rs:1:14 +error: `self` cannot be a raw identifier + --> $DIR/raw-literal-self.rs:2:9 | -LL | fn self_test(r#self: u32) { - | ^^^^^^ +LL | let r#self; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/raw/raw-literal-underscore.rs b/src/test/ui/parser/raw/raw-literal-underscore.rs index bbedd395202cf..6d15f1e7f0afd 100644 --- a/src/test/ui/parser/raw/raw-literal-underscore.rs +++ b/src/test/ui/parser/raw/raw-literal-underscore.rs @@ -1,3 +1,4 @@ -fn underscore_test(r#_: u32) { - //~^ ERROR `r#_` is not currently supported. +fn main() { + let r#_; + //~^ ERROR `_` cannot be a raw identifier } diff --git a/src/test/ui/parser/raw/raw-literal-underscore.stderr b/src/test/ui/parser/raw/raw-literal-underscore.stderr index 9427b33afd8d4..d96b14f55a39b 100644 --- a/src/test/ui/parser/raw/raw-literal-underscore.stderr +++ b/src/test/ui/parser/raw/raw-literal-underscore.stderr @@ -1,8 +1,8 @@ -error: `r#_` is not currently supported. - --> $DIR/raw-literal-underscore.rs:1:20 +error: `_` cannot be a raw identifier + --> $DIR/raw-literal-underscore.rs:2:9 | -LL | fn underscore_test(r#_: u32) { - | ^^^ +LL | let r#_; + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr index fd34459e89766..541ecc1dd4eac 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -4,7 +4,7 @@ error: proc macro panicked LL | invalid_raw_ident!(); //~ ERROR proc macro panicked | ^^^^^^^^^^^^^^^^^^^^^ | - = help: message: `"self"` is not a valid raw identifier + = help: message: `self` cannot be a raw identifier error: aborting due to previous error From 0dd5ff147095c2c860ae24cd19bbc3a7bf775b3b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 2 Mar 2019 19:15:26 +0300 Subject: [PATCH 14/30] Rename `MetaItem::ident` to `MetaItem::path` --- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc/lint/levels.rs | 12 ++++++------ src/librustc/session/config.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_mir/dataflow/mod.rs | 2 +- src/librustdoc/clean/cfg.rs | 10 +++++----- src/librustdoc/html/render.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/attr/builtin.rs | 18 +++++++++--------- src/libsyntax/attr/mod.rs | 32 ++++++++++++++++---------------- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/mut_visit.rs | 3 +-- src/libsyntax/parse/attr.rs | 6 +++--- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pprust.rs | 6 +++--- src/libsyntax/test.rs | 2 +- 16 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 0a1dda7a9cffd..85e62c0804a4f 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -368,7 +368,7 @@ impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind { }); impl_stable_hash_for!(struct ::syntax::ast::MetaItem { - ident, + path, node, span }); diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 2430e83122803..1641439c2c565 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -220,7 +220,7 @@ impl<'a> LintLevelsBuilder<'a> { match item.node { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { - if item.ident == "reason" { + if item.path == "reason" { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; // FIXME (#55112): issue unused-attributes lint if we thereby @@ -260,7 +260,7 @@ impl<'a> LintLevelsBuilder<'a> { let mut err = bad_attr(li.span); if let Some(item) = li.meta_item() { if let ast::MetaItemKind::NameValue(_) = item.node { - if item.ident == "reason" { + if item.path == "reason" { err.help("reason in lint attribute must come last"); } } @@ -269,15 +269,15 @@ impl<'a> LintLevelsBuilder<'a> { continue; } }; - let tool_name = if meta_item.ident.segments.len() > 1 { - let tool_ident = meta_item.ident.segments[0].ident; + let tool_name = if meta_item.path.segments.len() > 1 { + let tool_ident = meta_item.path.segments[0].ident; if !attr::is_known_lint_tool(tool_ident) { span_err!( sess, tool_ident.span, E0710, "an unknown tool name found in scoped lint: `{}`", - meta_item.ident + meta_item.path ); continue; } @@ -286,7 +286,7 @@ impl<'a> LintLevelsBuilder<'a> { } else { None }; - let name = meta_item.ident.segments.last().expect("empty lint name").ident.name; + let name = meta_item.path.segments.last().expect("empty lint name").ident.name; match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span, reason); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 662cedbdd01d2..9c146295bfe84 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1806,7 +1806,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> ast::CrateConfig { match &mut parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { - if meta_item.ident.segments.len() != 1 { + if meta_item.path.segments.len() != 1 { error!("argument key must be an identifier"); } match &meta_item.node { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 52dbb618d0d11..eb323d3a67856 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -798,7 +798,7 @@ impl RustcDefaultCalls { let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - ident: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)), + path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)), node: ast::MetaItemKind::Word, span: DUMMY_SP, }); diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index c24a776605cb8..9a926cb22a066 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -145,7 +145,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD } else { sess.span_err( item.span, - &format!("{} attribute requires a path", item.ident)); + &format!("{} attribute requires a path", item.path)); return None; } } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 7ebcf2cbd912c..6e852e6515d5a 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -430,7 +430,7 @@ mod test { fn dummy_meta_item_word(name: &str) -> MetaItem { MetaItem { - ident: Path::from_ident(Ident::from_str(name)), + path: Path::from_ident(Ident::from_str(name)), node: MetaItemKind::Word, span: DUMMY_SP, } @@ -439,7 +439,7 @@ mod test { macro_rules! dummy_meta_item_list { ($name:ident, [$($list:ident),* $(,)?]) => { MetaItem { - ident: Path::from_ident(Ident::from_str(stringify!($name))), + path: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( dummy_spanned(NestedMetaItemKind::MetaItem( @@ -453,7 +453,7 @@ mod test { ($name:ident, [$($list:expr),* $(,)?]) => { MetaItem { - ident: Path::from_ident(Ident::from_str(stringify!($name))), + path: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( dummy_spanned(NestedMetaItemKind::MetaItem($list)), @@ -593,7 +593,7 @@ mod test { assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); let mi = MetaItem { - ident: Path::from_ident(Ident::from_str("all")), + path: Path::from_ident(Ident::from_str("all")), node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( Symbol::intern("done"), StrStyle::Cooked, @@ -628,7 +628,7 @@ mod test { fn test_parse_err() { with_globals(|| { let mi = MetaItem { - ident: Path::from_ident(Ident::from_str("foo")), + path: Path::from_ident(Ident::from_str("foo")), node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))), span: DUMMY_SP, }; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 7f6a1df6ff928..1a4c5c3efc866 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3717,7 +3717,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, } fn render_attribute(attr: &ast::MetaItem) -> Option { - let path = attr.ident.to_string(); + let path = attr.path.to_string(); if attr.is_word() { Some(path) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a01a5bb0a3638..287ec4c2fdc4e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -464,7 +464,7 @@ pub enum NestedMetaItemKind { /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct MetaItem { - pub ident: Path, + pub path: Path, pub node: MetaItemKind, pub span: Span, } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index d97f817931077..234a127acad1c 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -217,7 +217,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.ident.to_string())); + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string())); return false } if let Some(v) = meta.value_str() { @@ -246,7 +246,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, handle_errors( sess, mi.span, - AttrError::UnknownMetaItem(mi.ident.to_string(), expected), + AttrError::UnknownMetaItem(mi.path.to_string(), expected), ); continue 'outer } @@ -329,7 +329,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span, AttrError::UnknownMetaItem( - mi.ident.to_string(), + mi.path.to_string(), &["feature", "reason", "issue"] ), ); @@ -401,7 +401,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span, AttrError::UnknownMetaItem( - mi.ident.to_string(), &["since", "note"], + mi.path.to_string(), &["since", "note"], ), ); continue 'outer @@ -496,8 +496,8 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat gated_cfg.check_and_emit(sess, feats); } let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true }; - if cfg.ident.segments.len() != 1 { - return error(cfg.ident.span, "`cfg` predicate key must be an identifier"); + if cfg.path.segments.len() != 1 { + return error(cfg.path.span, "`cfg` predicate key must be an identifier"); } match &cfg.node { MetaItemKind::List(..) => { @@ -563,7 +563,7 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) }, _ => { span_err!(sess.span_diagnostic, cfg.span, E0537, - "invalid predicate `{}`", cfg.ident); + "invalid predicate `{}`", cfg.path); false } } @@ -618,7 +618,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors( - sess, meta.span, AttrError::MultipleItem(meta.ident.to_string()) + sess, meta.span, AttrError::MultipleItem(meta.path.to_string()) ); return false } @@ -656,7 +656,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, handle_errors( sess, meta.span(), - AttrError::UnknownMetaItem(mi.ident.to_string(), + AttrError::UnknownMetaItem(mi.path.to_string(), &["since", "note"]), ); continue 'outer diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 857325681c660..dd3bc3f0c3627 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -208,8 +208,8 @@ impl Attribute { impl MetaItem { /// For a single-segment meta-item returns its name, otherwise returns `None`. pub fn ident(&self) -> Option { - if self.ident.segments.len() == 1 { - Some(self.ident.segments[0].ident) + if self.path.segments.len() == 1 { + Some(self.path.segments[0].ident) } else { None } @@ -256,7 +256,7 @@ impl MetaItem { pub fn span(&self) -> Span { self.span } pub fn check_name(&self, name: &str) -> bool { - self.ident == name + self.path == name } pub fn is_value_str(&self) -> bool { @@ -273,7 +273,7 @@ impl Attribute { pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { - ident: self.path.clone(), + path: self.path.clone(), node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { if tokens.peek().is_some() { return None; @@ -319,7 +319,7 @@ impl Attribute { pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { Ok(MetaItem { - ident: self.path.clone(), + path: self.path.clone(), node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, span: self.span, }) @@ -357,15 +357,15 @@ pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem } pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem { - MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } + MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } } pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { - MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) } + MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::List(items) } } pub fn mk_word_item(ident: Ident) -> MetaItem { - MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } + MetaItem { path: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } } pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { @@ -393,7 +393,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Inner, - path: item.ident, + path: item.path, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -410,7 +410,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Outer, - path: item.ident, + path: item.path, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -461,7 +461,7 @@ impl MetaItem { fn tokens(&self) -> TokenStream { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); - for (i, segment) in self.ident.segments.iter().enumerate() { + for (i, segment) in self.path.segments.iter().enumerate() { let is_first = i == 0; if !is_first { let mod_sep_span = Span::new(last_pos, @@ -481,7 +481,7 @@ impl MetaItem { where I: Iterator, { // FIXME: Share code with `parse_path`. - let ident = match tokens.next() { + let path = match tokens.next() { Some(TokenTree::Token(span, token @ Token::Ident(..))) | Some(TokenTree::Token(span, token @ Token::ModSep)) => 'arm: { let mut segments = if let Token::Ident(ident, _) = token { @@ -522,11 +522,11 @@ impl MetaItem { let node = MetaItemKind::from_tokens(tokens)?; let hi = match node { MetaItemKind::NameValue(ref lit) => lit.span.hi(), - MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span.hi()), - _ => ident.span.hi(), + MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()), + _ => path.span.hi(), }; - let span = ident.span.with_hi(hi); - Some(MetaItem { ident, node, span }) + let span = path.span.with_hi(hi); + Some(MetaItem { path, node, span }) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 46342e162cf9b..f64c49acd57e8 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -929,7 +929,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this - ident: Path::from_ident(keywords::Invalid.ident()), + path: Path::from_ident(keywords::Invalid.ident()), span: DUMMY_SP, node: ast::MetaItemKind::Word, }; diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 802b780869597..355e7fec3c9aa 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -548,7 +548,7 @@ pub fn noop_visit_meta_list_item(li: &mut NestedMetaItem, vis: &m } pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { - let MetaItem { ident: _, node, span } = mi; + let MetaItem { path: _, node, span } = mi; match node { MetaItemKind::Word => {} MetaItemKind::List(mis) => visit_vec(mis, |mi| vis.visit_meta_list_item(mi)), @@ -1340,4 +1340,3 @@ mod tests { }) } } - diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index e7937f57002f3..711a0f1ebeb72 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -149,7 +149,7 @@ impl<'a> Parser<'a> { }; Ok(if let Some(meta) = meta { self.bump(); - (meta.ident, meta.node.tokens(meta.span)) + (meta.path, meta.node.tokens(meta.span)) } else { let path = self.parse_path(PathStyle::Mod)?; let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) || @@ -250,10 +250,10 @@ impl<'a> Parser<'a> { } let lo = self.span; - let ident = self.parse_path(PathStyle::Mod)?; + let path = self.parse_path(PathStyle::Mod)?; let node = self.parse_meta_item_kind()?; let span = lo.to(self.prev_span); - Ok(ast::MetaItem { ident, node, span }) + Ok(ast::MetaItem { path, node, span }) } crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bb13077627491..646307b6820df 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2318,7 +2318,7 @@ impl<'a> Parser<'a> { let meta_ident = match self.token { token::Interpolated(ref nt) => match **nt { token::NtMeta(ref meta) => match meta.node { - ast::MetaItemKind::Word => Some(meta.ident.clone()), + ast::MetaItemKind::Word => Some(meta.path.clone()), _ => None, }, _ => None, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 49e3fad4af0ff..0fb8de984a95c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -781,15 +781,15 @@ pub trait PrintState<'a> { fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> { self.ibox(INDENT_UNIT)?; match item.node { - ast::MetaItemKind::Word => self.print_attribute_path(&item.ident)?, + ast::MetaItemKind::Word => self.print_attribute_path(&item.path)?, ast::MetaItemKind::NameValue(ref value) => { - self.print_attribute_path(&item.ident)?; + self.print_attribute_path(&item.path)?; self.writer().space()?; self.word_space("=")?; self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - self.print_attribute_path(&item.ident)?; + self.print_attribute_path(&item.path)?; self.popen()?; self.commasep(Consistent, &items[..], diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 3afd55899c8f6..0c1a292a937db 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -439,7 +439,7 @@ fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option meta_item.ident.clone(), + Some(meta_item) if meta_item.is_word() => meta_item.path.clone(), _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise() } }) From f922e0d81bca9497219fd2e554c1cb8818138ecf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 3 Mar 2019 20:56:24 +0300 Subject: [PATCH 15/30] Refactor away `NestedMetaItemKind` Remove methods `Attribute::span` and `MetaItem::span` duplicating public fields --- src/librustc/hir/check_attr.rs | 4 +- src/librustc/ich/impls_syntax.rs | 4 +- src/librustc/lint/levels.rs | 20 +++---- src/librustc/traits/on_unimplemented.rs | 4 +- src/librustc_incremental/assert_dep_graph.rs | 2 +- .../assert_module_sources.rs | 2 +- .../persist/dirty_clean.rs | 6 +- src/librustc_metadata/native_libs.rs | 2 +- src/librustc_passes/layout_test.rs | 2 +- src/librustc_plugin/load.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_typeck/collect.rs | 12 ++-- src/librustdoc/clean/cfg.rs | 14 ++--- src/librustdoc/clean/mod.rs | 6 +- src/libsyntax/ast.rs | 7 +-- src/libsyntax/attr/builtin.rs | 56 +++++++++---------- src/libsyntax/attr/mod.rs | 51 +++++++---------- src/libsyntax/config.rs | 4 +- src/libsyntax/ext/expand.rs | 14 ++--- src/libsyntax/feature_gate.rs | 16 +++--- src/libsyntax/mut_visit.rs | 8 +-- src/libsyntax/parse/attr.rs | 5 +- src/libsyntax/print/pprust.rs | 6 +- src/libsyntax/test.rs | 2 +- src/libsyntax_ext/proc_macro_decls.rs | 14 ++--- src/libsyntax_ext/test.rs | 2 +- 26 files changed, 125 insertions(+), 144 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index a97d7cb869021..9f550bbc56997 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -233,7 +233,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { _ => continue, }; self.emit_repr_error( - hint.span, + hint.span(), item.span, &format!("attribute should be applied to {}", allowed_targets), &format!("not {} {}", article, allowed_targets), @@ -242,7 +242,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { // Just point at all repr hints if there are any incompatibilities. // This is not ideal, but tracking precisely which ones are at fault is a huge hassle. - let hint_spans = hints.iter().map(|hint| hint.span); + let hint_spans = hints.iter().map(|hint| hint.span()); // Error on repr(transparent, ). if is_transparent && hints.len() > 1 { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 85e62c0804a4f..496ccc888b61a 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -360,9 +360,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>( } } -impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind); - -impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind { +impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItem { MetaItem(meta_item), Literal(lit) }); diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 1641439c2c565..2b2b109a9a744 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -257,7 +257,7 @@ impl<'a> LintLevelsBuilder<'a> { let meta_item = match li.meta_item() { Some(meta_item) if meta_item.is_word() => meta_item, _ => { - let mut err = bad_attr(li.span); + let mut err = bad_attr(li.span()); if let Some(item) = li.meta_item() { if let ast::MetaItemKind::NameValue(_) = item.node { if item.path == "reason" { @@ -289,7 +289,7 @@ impl<'a> LintLevelsBuilder<'a> { let name = meta_item.path.segments.last().expect("empty lint name").ident.name; match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { - let src = LintSource::Node(name, li.span, reason); + let src = LintSource::Node(name, li.span(), reason); for id in ids { specs.insert(*id, (level, src)); } @@ -300,7 +300,7 @@ impl<'a> LintLevelsBuilder<'a> { Ok(ids) => { let complete_name = &format!("{}::{}", tool_name.unwrap(), name); let src = LintSource::Node( - Symbol::intern(complete_name), li.span, reason + Symbol::intern(complete_name), li.span(), reason ); for id in ids { specs.insert(*id, (level, src)); @@ -322,18 +322,18 @@ impl<'a> LintLevelsBuilder<'a> { lint, lvl, src, - Some(li.span.into()), + Some(li.span().into()), &msg, ); err.span_suggestion( - li.span, + li.span(), "change it to", new_lint_name.to_string(), Applicability::MachineApplicable, ).emit(); let src = LintSource::Node( - Symbol::intern(&new_lint_name), li.span, reason + Symbol::intern(&new_lint_name), li.span(), reason ); for id in ids { specs.insert(*id, (level, src)); @@ -360,11 +360,11 @@ impl<'a> LintLevelsBuilder<'a> { lint, level, src, - Some(li.span.into()), + Some(li.span().into()), &msg); if let Some(new_name) = renamed { err.span_suggestion( - li.span, + li.span(), "use the new name", new_name, Applicability::MachineApplicable @@ -383,12 +383,12 @@ impl<'a> LintLevelsBuilder<'a> { lint, level, src, - Some(li.span.into()), + Some(li.span().into()), &msg); if let Some(suggestion) = suggestion { db.span_suggestion( - li.span, + li.span(), "did you mean", suggestion.to_string(), Applicability::MachineApplicable, diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index e6d77f1537cd5..13082f4fada2d 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { { if let Some(items) = item.meta_item_list() { if let Ok(subcommand) = - Self::parse(tcx, trait_def_id, &items, item.span, false) + Self::parse(tcx, trait_def_id, &items, item.span(), false) { subcommands.push(subcommand); } else { @@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { } // nothing found - parse_error(tcx, item.span, + parse_error(tcx, item.span(), "this attribute must have a valid value", "expected value here", Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 4d55c5aa0c07b..2e7864f4621fc 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { value = Some(ident.name), _ => // FIXME better-encapsulate meta_item (don't directly access `node`) - span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node), + span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item), } } value diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 5cbb412052dda..2c83501c86f52 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { return value; } else { self.tcx.sess.span_fatal( - item.span, + item.span(), &format!("associated value expected for `{}`", name)); } } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index eff502a26425e..28700edeaec68 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -430,13 +430,13 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if DepNode::has_label_string(label) { if out.contains(label) { self.tcx.sess.span_fatal( - item.span, + item.span(), &format!("dep-node label `{}` is repeated", label)); } out.insert(label.to_string()); } else { self.tcx.sess.span_fatal( - item.span, + item.span(), &format!("dep-node label `{}` not recognized", label)); } } @@ -582,7 +582,7 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as "expected an associated value".to_string() }; - tcx.sess.span_fatal(item.span, &msg); + tcx.sess.span_fatal(item.span(), &msg); } } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 23898387cba46..80786992cd956 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { k => { struct_span_err!(self.tcx.sess, m.span, E0458, "unknown kind: `{}`", k) - .span_label(item.span, "unknown kind").emit(); + .span_label(item.span(), "unknown kind").emit(); cstore::NativeUnknown } }; diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs index e2a74f5c4285b..373bcf7f0e2f3 100644 --- a/src/librustc_passes/layout_test.rs +++ b/src/librustc_passes/layout_test.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> VarianceTest<'a, 'tcx> { _ => { self.tcx.sess.span_err( - meta_item.span, + meta_item.span(), &format!("unrecognized field name `{}`", name), ); } diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 2f4332e71237d..bd11e0ce8023a 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -59,7 +59,7 @@ pub fn load_plugins(sess: &Session, match plugin.ident_str() { Some(name) if !plugin.is_value_str() => { let args = plugin.meta_item_list().map(ToOwned::to_owned); - loader.load_plugin(plugin.span, name, args.unwrap_or_default()); + loader.load_plugin(plugin.span(), name, args.unwrap_or_default()); }, _ => call_malformed_plugin_attribute(sess, attr.span), } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 174a921f0f398..8c61d8bce643f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -816,12 +816,12 @@ impl<'a> Resolver<'a> { MetaItemKind::List(nested_metas) => for nested_meta in nested_metas { match nested_meta.ident() { Some(ident) if nested_meta.is_word() => single_imports.push(ident), - _ => ill_formed(nested_meta.span), + _ => ill_formed(nested_meta.span()), } } MetaItemKind::NameValue(..) => ill_formed(meta.span), } - None => ill_formed(attr.span()), + None => ill_formed(attr.span), } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 594e29ab9ddea..2c6d2d3cc3984 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2269,7 +2269,7 @@ fn from_target_feature( if !item.check_name("enable") { let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \ currently"; - tcx.sess.span_err(item.span, &msg); + tcx.sess.span_err(item.span(), &msg); continue; } @@ -2279,7 +2279,7 @@ fn from_target_feature( None => { let msg = "#[target_feature] attribute must be of the form \ #[target_feature(enable = \"..\")]"; - tcx.sess.span_err(item.span, &msg); + tcx.sess.span_err(item.span(), &msg); continue; } }; @@ -2295,7 +2295,7 @@ fn from_target_feature( this target", feature ); - let mut err = tcx.sess.struct_span_err(item.span, &msg); + let mut err = tcx.sess.struct_span_err(item.span(), &msg); if feature.starts_with("+") { let valid = whitelist.contains_key(&feature[1..]); @@ -2330,7 +2330,7 @@ fn from_target_feature( feature_gate::emit_feature_err( &tcx.sess.parse_sess, feature_gate.as_ref().unwrap(), - item.span, + item.span(), feature_gate::GateIssue::Language, &format!("the target feature `{}` is currently unstable", feature), ); @@ -2492,7 +2492,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } else { span_err!( tcx.sess.diagnostic(), - items[0].span, + items[0].span(), E0535, "invalid argument" ); @@ -2526,7 +2526,7 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } else if list_contains_name(&items[..], "speed") { OptimizeAttr::Speed } else { - err(items[0].span, "invalid argument"); + err(items[0].span(), "invalid argument"); OptimizeAttr::None } } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 6e852e6515d5a..69445451503cc 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -8,7 +8,7 @@ use std::fmt::{self, Write}; use std::ops; use syntax::symbol::Symbol; -use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, LitKind}; +use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind}; use syntax::parse::ParseSess; use syntax::feature_gate::Features; @@ -41,9 +41,9 @@ pub struct InvalidCfgError { impl Cfg { /// Parses a `NestedMetaItem` into a `Cfg`. fn parse_nested(nested_cfg: &NestedMetaItem) -> Result { - match nested_cfg.node { - NestedMetaItemKind::MetaItem(ref cfg) => Cfg::parse(cfg), - NestedMetaItemKind::Literal(ref lit) => Err(InvalidCfgError { + match nested_cfg { + NestedMetaItem::MetaItem(ref cfg) => Cfg::parse(cfg), + NestedMetaItem::Literal(ref lit) => Err(InvalidCfgError { msg: "unexpected literal", span: lit.span, }), @@ -442,9 +442,9 @@ mod test { path: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( - dummy_spanned(NestedMetaItemKind::MetaItem( + NestedMetaItem::MetaItem( dummy_meta_item_word(stringify!($list)), - )), + ), )* ]), span: DUMMY_SP, @@ -456,7 +456,7 @@ mod test { path: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( - dummy_spanned(NestedMetaItemKind::MetaItem($list)), + NestedMetaItem::MetaItem($list), )* ]), span: DUMMY_SP, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 929d8404a8ce8..a6d1cb6c53ed6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -776,15 +776,15 @@ pub struct Attributes { impl Attributes { /// Extracts the content from an attribute `#[doc(cfg(content))]`. fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> { - use syntax::ast::NestedMetaItemKind::MetaItem; + use syntax::ast::NestedMetaItem::MetaItem; if let ast::MetaItemKind::List(ref nmis) = mi.node { if nmis.len() == 1 { - if let MetaItem(ref cfg_mi) = nmis[0].node { + if let MetaItem(ref cfg_mi) = nmis[0] { if cfg_mi.check_name("cfg") { if let ast::MetaItemKind::List(ref cfg_nmis) = cfg_mi.node { if cfg_nmis.len() == 1 { - if let MetaItem(ref content_mi) = cfg_nmis[0].node { + if let MetaItem(ref content_mi) = cfg_nmis[0] { return Some(content_mi); } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 287ec4c2fdc4e..1a0da73880cfc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -443,14 +443,11 @@ pub struct Crate { pub span: Span, } -/// A spanned compile-time attribute list item. -pub type NestedMetaItem = Spanned; - /// Possible values inside of compile-time attribute lists. /// /// E.g., the '..' in `#[name(..)]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum NestedMetaItemKind { +pub enum NestedMetaItem { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), /// A literal. @@ -2207,7 +2204,7 @@ pub struct Item { impl Item { /// Return the span that encompasses the attributes. pub fn span_with_attributes(&self) -> Span { - self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span())) + self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span)) } } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 234a127acad1c..8ccc59372986b 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -1,6 +1,6 @@ //! Parsing and validation of builtin attributes -use crate::ast::{self, Attribute, MetaItem, NestedMetaItemKind}; +use crate::ast::{self, Attribute, MetaItem, NestedMetaItem}; use crate::feature_gate::{Features, GatedCfg}; use crate::parse::ParseSess; @@ -254,7 +254,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } else { handle_errors( sess, - meta.span, + meta.span(), AttrError::UnsupportedLiteral( "unsupported literal", false, @@ -285,11 +285,11 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, }) } (None, _) => { - handle_errors(sess, attr.span(), AttrError::MissingSince); + handle_errors(sess, attr.span, AttrError::MissingSince); continue } _ => { - span_err!(diagnostic, attr.span(), E0543, "missing 'reason'"); + span_err!(diagnostic, attr.span, E0543, "missing 'reason'"); continue } } @@ -305,13 +305,13 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, if let Some(feature) = feature { rustc_const_unstable = Some(feature); } else { - span_err!(diagnostic, attr.span(), E0629, "missing 'feature'"); + span_err!(diagnostic, attr.span, E0629, "missing 'feature'"); continue } } "unstable" => { if stab.is_some() { - handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels); + handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); break } @@ -327,7 +327,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, _ => { handle_errors( sess, - meta.span, + meta.span(), AttrError::UnknownMetaItem( mi.path.to_string(), &["feature", "reason", "issue"] @@ -339,7 +339,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } else { handle_errors( sess, - meta.span, + meta.span(), AttrError::UnsupportedLiteral( "unsupported literal", false, @@ -358,7 +358,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, if let Ok(issue) = issue.as_str().parse() { issue } else { - span_err!(diagnostic, attr.span(), E0545, + span_err!(diagnostic, attr.span, E0545, "incorrect 'issue'"); continue } @@ -371,26 +371,26 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, }) } (None, _, _) => { - handle_errors(sess, attr.span(), AttrError::MissingFeature); + handle_errors(sess, attr.span, AttrError::MissingFeature); continue } _ => { - span_err!(diagnostic, attr.span(), E0547, "missing 'issue'"); + span_err!(diagnostic, attr.span, E0547, "missing 'issue'"); continue } } } "stable" => { if stab.is_some() { - handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels); + handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels); break } let mut feature = None; let mut since = None; for meta in metas { - match &meta.node { - NestedMetaItemKind::MetaItem(mi) => { + match meta { + NestedMetaItem::MetaItem(mi) => { match mi.ident_str() { Some("feature") => if !get(mi, &mut feature) { continue 'outer }, @@ -399,7 +399,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, _ => { handle_errors( sess, - meta.span, + meta.span(), AttrError::UnknownMetaItem( mi.path.to_string(), &["since", "note"], ), @@ -408,7 +408,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, } } }, - NestedMetaItemKind::Literal(lit) => { + NestedMetaItem::Literal(lit) => { handle_errors( sess, lit.span, @@ -435,11 +435,11 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, }) } (None, _) => { - handle_errors(sess, attr.span(), AttrError::MissingFeature); + handle_errors(sess, attr.span, AttrError::MissingFeature); continue } _ => { - handle_errors(sess, attr.span(), AttrError::MissingSince); + handle_errors(sess, attr.span, AttrError::MissingSince); continue } } @@ -534,7 +534,7 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) if !mi.is_meta_item() { handle_errors( sess, - mi.span, + mi.span(), AttrError::UnsupportedLiteral( "unsupported literal", false @@ -647,8 +647,8 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let mut since = None; let mut note = None; for meta in list { - match &meta.node { - NestedMetaItemKind::MetaItem(mi) => { + match meta { + NestedMetaItem::MetaItem(mi) => { match mi.ident_str() { Some("since") => if !get(mi, &mut since) { continue 'outer }, Some("note") => if !get(mi, &mut note) { continue 'outer }, @@ -663,7 +663,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, } } } - NestedMetaItemKind::Literal(lit) => { + NestedMetaItem::Literal(lit) => { handle_errors( sess, lit.span, @@ -732,7 +732,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { if !item.is_meta_item() { handle_errors( sess, - item.span, + item.span(), AttrError::UnsupportedLiteral( "meta item in `repr` must be an identifier", false, @@ -789,7 +789,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { }; } if let Some(literal_error) = literal_error { - span_err!(diagnostic, item.span, E0589, + span_err!(diagnostic, item.span(), E0589, "invalid `repr(align)` attribute: {}", literal_error); } } else { @@ -797,12 +797,12 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { if meta_item.check_name("align") { if let MetaItemKind::NameValue(ref value) = meta_item.node { recognised = true; - let mut err = struct_span_err!(diagnostic, item.span, E0693, + let mut err = struct_span_err!(diagnostic, item.span(), E0693, "incorrect `repr(align)` attribute format"); match value.node { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { err.span_suggestion( - item.span, + item.span(), "use parentheses instead", format!("align({})", int), Applicability::MachineApplicable @@ -810,7 +810,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { } ast::LitKind::Str(s, _) => { err.span_suggestion( - item.span, + item.span(), "use parentheses instead", format!("align({})", s), Applicability::MachineApplicable @@ -825,7 +825,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec { } if !recognised { // Not a word we recognize - span_err!(diagnostic, item.span, E0552, + span_err!(diagnostic, item.span(), E0552, "unrecognized representation hint"); } } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index dd3bc3f0c3627..1a8faa43fff7c 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -13,7 +13,7 @@ pub use StabilityLevel::*; use crate::ast; use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment}; -use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; +use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; use crate::source_map::{BytePos, Spanned, respan, dummy_spanned}; @@ -64,27 +64,22 @@ pub fn is_known_lint_tool(m_item: Ident) -> bool { } impl NestedMetaItem { - /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem. + /// Returns the MetaItem if self is a NestedMetaItem::MetaItem. pub fn meta_item(&self) -> Option<&MetaItem> { - match self.node { - NestedMetaItemKind::MetaItem(ref item) => Some(item), + match *self { + NestedMetaItem::MetaItem(ref item) => Some(item), _ => None } } - /// Returns the Lit if self is a NestedMetaItemKind::Literal. + /// Returns the Lit if self is a NestedMetaItem::Literal. pub fn literal(&self) -> Option<&Lit> { - match self.node { - NestedMetaItemKind::Literal(ref lit) => Some(lit), + match *self { + NestedMetaItem::Literal(ref lit) => Some(lit), _ => None } } - /// Returns the Span for `self`. - pub fn span(&self) -> Span { - self.span - } - /// Returns `true` if this list item is a MetaItem with a name of `name`. pub fn check_name(&self, name: &str) -> bool { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) @@ -191,10 +186,6 @@ impl Attribute { self.tokens.is_empty() } - pub fn span(&self) -> Span { - self.span - } - pub fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() } @@ -253,8 +244,6 @@ impl MetaItem { } } - pub fn span(&self) -> Span { self.span } - pub fn check_name(&self, name: &str) -> bool { self.path == name } @@ -369,7 +358,7 @@ pub fn mk_word_item(ident: Ident) -> MetaItem { } pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { - respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident))) + NestedMetaItem::MetaItem(mk_word_item(ident)) } pub fn mk_attr_id() -> AttrId { @@ -545,7 +534,7 @@ impl MetaItemKind { if i > 0 { tokens.push(TokenTree::Token(span, Token::Comma).into()); } - item.node.tokens().append_to_tree_and_joint_vec(&mut tokens); + item.tokens().append_to_tree_and_joint_vec(&mut tokens); } TokenTree::Delimited( DelimSpan::from_single(span), @@ -579,8 +568,8 @@ impl MetaItemKind { let mut tokens = delimited.into_trees().peekable(); let mut result = Vec::new(); while let Some(..) = tokens.peek() { - let item = NestedMetaItemKind::from_tokens(&mut tokens)?; - result.push(respan(item.span(), item)); + let item = NestedMetaItem::from_tokens(&mut tokens)?; + result.push(item); match tokens.next() { None | Some(TokenTree::Token(_, Token::Comma)) => {} _ => return None, @@ -590,32 +579,32 @@ impl MetaItemKind { } } -impl NestedMetaItemKind { - fn span(&self) -> Span { +impl NestedMetaItem { + pub fn span(&self) -> Span { match *self { - NestedMetaItemKind::MetaItem(ref item) => item.span, - NestedMetaItemKind::Literal(ref lit) => lit.span, + NestedMetaItem::MetaItem(ref item) => item.span, + NestedMetaItem::Literal(ref lit) => lit.span, } } fn tokens(&self) -> TokenStream { match *self { - NestedMetaItemKind::MetaItem(ref item) => item.tokens(), - NestedMetaItemKind::Literal(ref lit) => lit.tokens(), + NestedMetaItem::MetaItem(ref item) => item.tokens(), + NestedMetaItem::Literal(ref lit) => lit.tokens(), } } - fn from_tokens(tokens: &mut iter::Peekable) -> Option + fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { if let Some(node) = LitKind::from_token(token) { tokens.next(); - return Some(NestedMetaItemKind::Literal(respan(span, node))); + return Some(NestedMetaItem::Literal(respan(span, node))); } } - MetaItem::from_tokens(tokens).map(NestedMetaItemKind::MetaItem) + MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem) } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 4e4432a3f334d..3b9a38932aa08 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -181,13 +181,13 @@ impl<'a> StripUnconfigured<'a> { if nested_meta_items.is_empty() { return error(meta_item.span, "`cfg` predicate is not specified", ""); } else if nested_meta_items.len() > 1 { - return error(nested_meta_items.last().unwrap().span, + return error(nested_meta_items.last().unwrap().span(), "multiple `cfg` predicates are specified", ""); } match nested_meta_items[0].meta_item() { Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), - None => error(nested_meta_items[0].span, + None => error(nested_meta_items[0].span(), "`cfg` predicate key cannot be a literal", ""), } }) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f64c49acd57e8..82358679c0e82 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1520,23 +1520,23 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.cx.source_map().new_source_file(filename.into(), src); let include_info = vec![ - dummy_spanned(ast::NestedMetaItemKind::MetaItem( + ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( Ident::from_str("file"), dummy_spanned(file), ), - )), - dummy_spanned(ast::NestedMetaItemKind::MetaItem( + ), + ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( Ident::from_str("contents"), dummy_spanned(src_interned), ), - )), + ), ]; let include_ident = Ident::from_str("include"); let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); - items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item))); + items.push(ast::NestedMetaItem::MetaItem(item)); } Err(e) => { let lit = it @@ -1569,7 +1569,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } else { let mut err = self.cx.struct_span_err( - it.span, + it.span(), &format!("expected path to external documentation"), ); @@ -1590,7 +1590,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }; err.span_suggestion( - it.span, + it.span(), "provide a file path with `=`", format!("include = \"{}\"", path), applicability, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b8281b3bf58f2..6d8e32a01a68b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -2061,7 +2061,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], if incomplete_features.iter().any(|f| *f == name) { span_handler.struct_span_warn( - mi.span, + mi.span(), &format!( "the feature `{}` is incomplete and may cause the compiler to crash", name @@ -2102,7 +2102,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let name = match mi.ident() { Some(ident) if mi.is_word() => ident.name, _ => { - span_err!(span_handler, mi.span, E0556, + span_err!(span_handler, mi.span(), E0556, "malformed feature, expected just one word"); continue } @@ -2111,7 +2111,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], if let Some(edition) = edition_enabled_features.get(&name) { struct_span_warn!( span_handler, - mi.span, + mi.span(), E0705, "the feature `{}` is included in the Rust {} edition", name, @@ -2126,25 +2126,25 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) { - set(&mut features, mi.span); - features.declared_lang_features.push((name, mi.span, None)); + set(&mut features, mi.span()); + features.declared_lang_features.push((name, mi.span(), None)); continue } let removed = REMOVED_FEATURES.iter().find(|f| name == f.0); let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0); if let Some((.., reason)) = removed.or(stable_removed) { - feature_removed(span_handler, mi.span, *reason); + feature_removed(span_handler, mi.span(), *reason); continue } if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) { let since = Some(Symbol::intern(since)); - features.declared_lang_features.push((name, mi.span, since)); + features.declared_lang_features.push((name, mi.span(), since)); continue } - features.declared_lib_features.push((name, mi.span)); + features.declared_lib_features.push((name, mi.span())); } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 355e7fec3c9aa..462346df7d76d 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -539,12 +539,10 @@ pub fn noop_visit_macro_def(macro_def: &mut MacroDef, vis: &mut T } pub fn noop_visit_meta_list_item(li: &mut NestedMetaItem, vis: &mut T) { - let Spanned { node, span } = li; - match node { - NestedMetaItemKind::MetaItem(mi) => vis.visit_meta_item(mi), - NestedMetaItemKind::Literal(_lit) => {} + match li { + NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi), + NestedMetaItem::Literal(_lit) => {} } - vis.visit_span(span); } pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 711a0f1ebeb72..61e3d7146e1b5 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -1,6 +1,5 @@ use crate::attr; use crate::ast; -use crate::source_map::respan; use crate::parse::{SeqSep, PResult}; use crate::parse::token::{self, Nonterminal, DelimToken}; use crate::parse::parser::{Parser, TokenType, PathStyle}; @@ -272,14 +271,14 @@ impl<'a> Parser<'a> { match self.parse_unsuffixed_lit() { Ok(lit) => { - return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::Literal(lit))) + return Ok(ast::NestedMetaItem::Literal(lit)) } Err(ref mut err) => self.diagnostic().cancel(err) } match self.parse_meta_item() { Ok(mi) => { - return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::MetaItem(mi))) + return Ok(ast::NestedMetaItem::MetaItem(mi)) } Err(ref mut err) => self.diagnostic().cancel(err) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0fb8de984a95c..e04e127ccf15a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -768,11 +768,11 @@ pub trait PrintState<'a> { } fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> { - match item.node { - ast::NestedMetaItemKind::MetaItem(ref mi) => { + match item { + ast::NestedMetaItem::MetaItem(ref mi) => { self.print_meta_item(mi) }, - ast::NestedMetaItemKind::Literal(ref lit) => { + ast::NestedMetaItem::Literal(ref lit) => { self.print_literal(lit) } } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 0c1a292a937db..6f03c5854036c 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -435,7 +435,7 @@ fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option CollectProcMacros<'a> { None => return, }; if list.len() != 1 && list.len() != 2 { - self.handler.span_err(attr.span(), + self.handler.span_err(attr.span, "attribute must have either one or two arguments"); return } @@ -129,7 +129,7 @@ impl<'a> CollectProcMacros<'a> { }; if !trait_ident.can_be_raw() { - self.handler.span_err(trait_attr.span(), + self.handler.span_err(trait_attr.span, &format!("`{}` cannot be a name of derive macro", trait_ident)); } if deriving::is_builtin_trait(trait_ident.name) { @@ -164,7 +164,7 @@ impl<'a> CollectProcMacros<'a> { }; if !ident.can_be_raw() { self.handler.span_err( - attr.span(), + attr.span, &format!("`{}` cannot be a name of derive helper attribute", ident), ); } @@ -262,8 +262,8 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { to the same function", attr.path, prev_attr.path) }; - self.handler.struct_span_err(attr.span(), &msg) - .span_note(prev_attr.span(), "Previous attribute here") + self.handler.struct_span_err(attr.span, &msg) + .span_note(prev_attr.span, "Previous attribute here") .emit(); return; @@ -288,7 +288,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { let msg = format!("the `#[{}]` attribute may only be used on bare functions", attr.path); - self.handler.span_err(attr.span(), &msg); + self.handler.span_err(attr.span, &msg); return; } @@ -300,7 +300,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { let msg = format!("the `#[{}]` attribute is only usable with crates of the \ `proc-macro` crate type", attr.path); - self.handler.span_err(attr.span(), &msg); + self.handler.span_err(attr.span, &msg); return; } diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index f4b625f8ea2c8..0dbcb7ce0b7e2 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -227,7 +227,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { .and_then(|mi| mi.value_str()); if list.len() != 1 || msg.is_none() { sd.struct_span_warn( - attr.span(), + attr.span, "argument must be of the form: \ `expected = \"error message\"`" ).note("Errors in this attribute were erroneously \ From c82a42c155aa4b4825cb8dc21e9e498a752af13f Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Sun, 3 Mar 2019 19:47:17 +0000 Subject: [PATCH 16/30] Change `std::fs::copy` to use `copyfile` on MacOS and iOS --- src/libstd/fs.rs | 3 +- src/libstd/sys/unix/fs.rs | 87 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 25f2dd73504ae..3454f847ef414 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1581,7 +1581,8 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// `O_CLOEXEC` is set for returned file descriptors. /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate /// NTFS streams are copied but only the size of the main stream is returned by -/// this function. +/// this function. On MacOS, this function corresponds to `copyfile` with +/// `COPYFILE_ALL` /// Note that, this [may change in the future][changes]. /// /// [changes]: ../io/index.html#platform-specific-behavior diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 3b80b475a93db..7ff098bc9e123 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -827,7 +827,10 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } -#[cfg(not(any(target_os = "linux", target_os = "android")))] +#[cfg(not(any(target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "ios")))] pub fn copy(from: &Path, to: &Path) -> io::Result { use crate::fs::File; if !from.is_file() { @@ -937,3 +940,85 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { writer.set_permissions(perm)?; Ok(written) } + +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub fn copy(from: &Path, to: &Path) -> io::Result { + const COPYFILE_ACL: u32 = 1 << 0; + const COPYFILE_STAT: u32 = 1 << 1; + const COPYFILE_XATTR: u32 = 1 << 2; + const COPYFILE_DATA: u32 = 1 << 3; + + const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL; + const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR; + const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA; + + const COPYFILE_STATE_COPIED: u32 = 8; + + #[allow(non_camel_case_types)] + type copyfile_state_t = *mut libc::c_void; + #[allow(non_camel_case_types)] + type copyfile_flags_t = u32; + + extern "C" { + fn copyfile( + from: *const libc::c_char, + to: *const libc::c_char, + state: copyfile_state_t, + flags: copyfile_flags_t, + ) -> libc::c_int; + fn copyfile_state_alloc() -> copyfile_state_t; + fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int; + fn copyfile_state_get( + state: copyfile_state_t, + flag: u32, + dst: *mut libc::c_void, + ) -> libc::c_int; + } + + struct FreeOnDrop(copyfile_state_t); + impl Drop for FreeOnDrop { + fn drop(&mut self) { + // The code below ensures that `FreeOnDrop` is never a null pointer + unsafe { + // `copyfile_state_free` returns -1 if the `to` or `from` files + // cannot be closed. However, this is not considerd this an + // error. + copyfile_state_free(self.0); + } + } + } + + if !from.is_file() { + return Err(Error::new(ErrorKind::InvalidInput, + "the source path is not an existing regular file")) + } + + // We ensure that `FreeOnDrop` never contains a null pointer so it is + // always safe to call `copyfile_state_free` + let state = unsafe { + let state = copyfile_state_alloc(); + if state.is_null() { + return Err(crate::io::Error::last_os_error()); + } + FreeOnDrop(state) + }; + + cvt(unsafe { + copyfile( + cstr(from)?.as_ptr(), + cstr(to)?.as_ptr(), + state.0, + COPYFILE_ALL, + ) + })?; + + let mut bytes_copied: libc::off_t = 0; + cvt(unsafe { + copyfile_state_get( + state.0, + COPYFILE_STATE_COPIED, + &mut bytes_copied as *mut libc::off_t as *mut libc::c_void, + ) + })?; + Ok(bytes_copied as u64) +} From 0a991e424a794d0d556602e88cd2ebf511b05de7 Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Mon, 4 Mar 2019 12:35:46 +0000 Subject: [PATCH 17/30] Add test for the behaviour of `fs::copy` when `to` is a symlink --- src/libstd/fs.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 3454f847ef414..7b9b5d4de206c 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2837,6 +2837,26 @@ mod tests { assert_eq!(check!(out_path.metadata()).len(), copied_len); } + #[test] + fn copy_file_follows_dst_symlink() { + let tmp = tmpdir(); + if !got_symlink_permission(&tmp) { return }; + + let in_path = tmp.join("in.txt"); + let out_path = tmp.join("out.txt"); + let out_path_symlink = tmp.join("out_symlink.txt"); + + check!(fs::write(&in_path, "foo")); + check!(fs::write(&out_path, "bar")); + check!(symlink_file(&out_path, &out_path_symlink)); + + check!(fs::copy(&in_path, &out_path_symlink)); + + assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink()); + assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec()); + assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec()); + } + #[test] fn symlinks_work() { let tmpdir = tmpdir(); From 124ab2a4d87f2d10b88d668e35286af4c00ec12b Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Mon, 4 Mar 2019 12:53:54 +0000 Subject: [PATCH 18/30] Fix typo --- src/libstd/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 7b9b5d4de206c..a03f55424a9cd 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1582,7 +1582,7 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate /// NTFS streams are copied but only the size of the main stream is returned by /// this function. On MacOS, this function corresponds to `copyfile` with -/// `COPYFILE_ALL` +/// `COPYFILE_ALL`. /// Note that, this [may change in the future][changes]. /// /// [changes]: ../io/index.html#platform-specific-behavior From 1243859d402427d90271d646968a6a4e5ad0052b Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Tue, 5 Mar 2019 13:43:48 +0000 Subject: [PATCH 19/30] core: ensure VaList passes improper_ctypes lint Ensure the core::ffi::VaList structure passes the improper_ctypes lint. --- src/libcore/ffi.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index d88793f2801e7..5cc9c25c21e0f 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -79,9 +79,9 @@ impl fmt::Debug for VaListImpl { all supported platforms", issue = "44930")] struct VaListImpl { - stack: *mut (), - gr_top: *mut (), - vr_top: *mut (), + stack: *mut c_void, + gr_top: *mut c_void, + vr_top: *mut c_void, gr_offs: i32, vr_offs: i32, } @@ -98,8 +98,8 @@ struct VaListImpl { gpr: u8, fpr: u8, reserved: u16, - overflow_arg_area: *mut (), - reg_save_area: *mut (), + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, } /// x86_64 ABI implementation of a `va_list`. @@ -113,8 +113,8 @@ struct VaListImpl { struct VaListImpl { gp_offset: i32, fp_offset: i32, - overflow_arg_area: *mut (), - reg_save_area: *mut (), + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, } /// A wrapper for a `va_list` From 72958acd57fb32e0f8027c0d7e76c9a0c7f155d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 1 Mar 2019 11:47:06 -0800 Subject: [PATCH 20/30] std: Spin for a global malloc lock on wasm32 There's lots of comments in the code, but the main gist of this commit is that the acquisition of the global malloc lock on the `wasm32-unknown-unknown` target when threads are enabled will not spin on contention rather than block. --- src/libstd/sys/wasm/alloc.rs | 95 ++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs index b9098548b9c1e..c1af6ec12623c 100644 --- a/src/libstd/sys/wasm/alloc.rs +++ b/src/libstd/sys/wasm/alloc.rs @@ -49,7 +49,6 @@ unsafe impl GlobalAlloc for System { #[cfg(target_feature = "atomics")] mod lock { - use crate::arch::wasm32; use crate::sync::atomic::{AtomicI32, Ordering::SeqCst}; static LOCKED: AtomicI32 = AtomicI32::new(0); @@ -61,14 +60,76 @@ mod lock { if LOCKED.swap(1, SeqCst) == 0 { return DropLock } - unsafe { - let r = wasm32::i32_atomic_wait( - &LOCKED as *const AtomicI32 as *mut i32, - 1, // expected value - -1, // timeout - ); - debug_assert!(r == 0 || r == 1); - } + // Ok so here's where things get a little depressing. At this point + // in time we need to synchronously acquire a lock, but we're + // contending with some other thread. Typically we'd execute some + // form of `i32.atomic.wait` like so: + // + // unsafe { + // let r = core::arch::wasm32::i32_atomic_wait( + // &LOCKED as *const AtomicI32 as *mut i32, + // 1, // expected value + // -1, // timeout + // ); + // debug_assert!(r == 0 || r == 1); + // } + // + // Unfortunately though in doing so we would cause issues for the + // main thread. The main thread in a web browser *cannot ever + // block*, no exceptions. This means that the main thread can't + // actually execute the `i32.atomic.wait` instruction. + // + // As a result if we want to work within the context of browsers we + // need to figure out some sort of allocation scheme for the main + // thread where when there's contention on the global malloc lock we + // do... something. + // + // Possible ideas include: + // + // 1. Attempt to acquire the global lock. If it fails, fall back to + // memory allocation via `memory.grow`. Later just ... somehow + // ... inject this raw page back into the main allocator as it + // gets sliced up over time. This strategy has the downside of + // forcing allocation of a page to happen whenever the main + // thread contents with other threads, which is unfortunate. + // + // 2. Maintain a form of "two level" allocator scheme where the main + // thread has its own allocator. Somehow this allocator would + // also be balanced with a global allocator, not only to have + // allocations cross between threads but also to ensure that the + // two allocators stay "balanced" in terms of free'd memory and + // such. This, however, seems significantly complicated. + // + // Out of a lack of other ideas, the current strategy implemented + // here is to simply spin. Typical spin loop algorithms have some + // form of "hint" here to the CPU that it's what we're doing to + // ensure that the CPU doesn't get too hot, but wasm doesn't have + // such an instruction. + // + // To be clear, spinning here is not a great solution. + // Another thread with the lock may take quite a long time to wake + // up. For example it could be in `memory.grow` or it could be + // evicted from the CPU for a timeslice like 10ms. For these periods + // of time our thread will "helpfully" sit here and eat CPU time + // until it itself is evicted or the lock holder finishes. This + // means we're just burning and wasting CPU time to no one's + // benefit. + // + // Spinning does have the nice properties, though, of being + // semantically correct, being fair to all threads for memory + // allocation, and being simple enough to implement. + // + // This will surely (hopefully) be replaced in the future with a + // real memory allocator that can handle the restriction of the main + // thread. + // + // + // FIXME: We can also possibly add an optimization here to detect + // when a thread is the main thread or not and block on all + // non-main-thread threads. Currently, however, we have no way + // of knowing which wasm thread is on the browser main thread, but + // if we could figure out we could at least somewhat mitigate the + // cost of this spinning. } } @@ -76,12 +137,16 @@ mod lock { fn drop(&mut self) { let r = LOCKED.swap(0, SeqCst); debug_assert_eq!(r, 1); - unsafe { - wasm32::atomic_notify( - &LOCKED as *const AtomicI32 as *mut i32, - 1, // only one thread - ); - } + + // Note that due to the above logic we don't actually need to wake + // anyone up, but if we did it'd likely look something like this: + // + // unsafe { + // core::arch::wasm32::atomic_notify( + // &LOCKED as *const AtomicI32 as *mut i32, + // 1, // only one thread + // ); + // } } } } From 710988ad603c52657c72a7f1028415e3e244a97c Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Tue, 5 Mar 2019 23:28:15 +0800 Subject: [PATCH 21/30] MIPS: add r6 support MIPS r6 is quite different with the previous version. It use some new target triples: mipsisa32r6-unknown-linux-gnu mipsisa32r6el-unknown-linux-gnu mipsisa64r6-unknown-linux-gnuabi64 mipsisa64r6el-unknown-linux-gnuabi64 This patch has been tested with Debian Port for mips64r6el, and the support of these triples also is included in llvm: https://reviews.llvm.org/rGe58c45a695f39004710b6ce940d489fee800dbd3 --- .../spec/mipsisa32r6_unknown_linux_gnu.rs | 23 ++++++++++++++++++ .../spec/mipsisa32r6el_unknown_linux_gnu.rs | 24 +++++++++++++++++++ .../mipsisa64r6_unknown_linux_gnuabi64.rs | 24 +++++++++++++++++++ .../mipsisa64r6el_unknown_linux_gnuabi64.rs | 24 +++++++++++++++++++ src/librustc_target/spec/mod.rs | 4 ++++ src/tools/build-manifest/src/main.rs | 8 +++++++ src/tools/compiletest/src/util.rs | 8 +++++++ 7 files changed, 115 insertions(+) create mode 100644 src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs create mode 100644 src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs create mode 100644 src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs create mode 100644 src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs diff --git a/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs new file mode 100644 index 0000000000000..f47291458492e --- /dev/null +++ b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs @@ -0,0 +1,23 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "mipsisa32r6-unknown-linux-gnu".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), + arch: "mips".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + cpu: "mips32r6".to_string(), + features: "+mips32r6".to_string(), + max_atomic_width: Some(32), + + ..super::linux_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs new file mode 100644 index 0000000000000..f4f98d33571f0 --- /dev/null +++ b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs @@ -0,0 +1,24 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "mipsisa32r6el-unknown-linux-gnu".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), + arch: "mips".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + cpu: "mips32r6".to_string(), + features: "+mips32r6".to_string(), + max_atomic_width: Some(32), + + ..super::linux_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs new file mode 100644 index 0000000000000..7faed3adc79cc --- /dev/null +++ b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -0,0 +1,24 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), + arch: "mips64".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + // NOTE(mips64r6) matches C toolchain + cpu: "mips64r6".to_string(), + features: "+mips64r6".to_string(), + max_atomic_width: Some(64), + + ..super::linux_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs new file mode 100644 index 0000000000000..58a814a759eb8 --- /dev/null +++ b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -0,0 +1,24 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), + arch: "mips64".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + // NOTE(mips64r6) matches C toolchain + cpu: "mips64r6".to_string(), + features: "+mips64r6".to_string(), + max_atomic_width: Some(64), + + ..super::linux_base::opts() + }, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index bef2afc7b6292..1020464ca0b06 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -335,6 +335,10 @@ supported_targets! { ("mips-unknown-linux-gnu", mips_unknown_linux_gnu), ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64), ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64), + ("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu), + ("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu), + ("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64), + ("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64), ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu), ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu), ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe), diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8d87c404d0b28..6eb12ea016186 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -23,6 +23,10 @@ static HOSTS: &'static [&'static str] = &[ "mips64-unknown-linux-gnuabi64", "mips64el-unknown-linux-gnuabi64", "mipsel-unknown-linux-gnu", + "mipsisa32r6-unknown-linux-gnu", + "mipsisa32r6el-unknown-linux-gnu", + "mipsisa64r6-unknown-linux-gnuabi64", + "mipsisa64r6el-unknown-linux-gnuabi64", "powerpc-unknown-linux-gnu", "powerpc64-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu", @@ -77,6 +81,10 @@ static TARGETS: &'static [&'static str] = &[ "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", "mips64el-unknown-linux-gnuabi64", + "mipsisa32r6-unknown-linux-gnu", + "mipsisa32r6el-unknown-linux-gnu", + "mipsisa64r6-unknown-linux-gnuabi64", + "mipsisa64r6el-unknown-linux-gnuabi64", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "nvptx64-nvidia-cuda", diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 240287fa248bd..3533dcdc988a1 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -49,7 +49,15 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("mips", "mips"), ("mips64", "mips64"), ("mips64el", "mips64"), + ("mipsisa32r6", "mips"), + ("mipsisa32r6el", "mips"), + ("mipsisa64r6", "mips64"), + ("mipsisa64r6el", "mips64"), ("mipsel", "mips"), + ("mipsisa32r6", "mips"), + ("mipsisa32r6el", "mips"), + ("mipsisa64r6", "mips64"), + ("mipsisa64r6el", "mips64"), ("msp430", "msp430"), ("powerpc", "powerpc"), ("powerpc64", "powerpc64"), From 7e8758bc8063ae52ef3f28ff77d5544565b364e0 Mon Sep 17 00:00:00 2001 From: Jordan Rhee Date: Tue, 5 Mar 2019 13:56:39 -0800 Subject: [PATCH 22/30] Update compiler_builtins to 0.1.7 --- Cargo.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19dadaa14005a..daa072c58841d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -106,7 +106,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -463,7 +463,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", @@ -748,7 +748,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -906,7 +906,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1739,7 +1739,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1749,7 +1749,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1954,7 +1954,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2485,7 +2485,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2585,7 +2585,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2813,7 +2813,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2864,7 +2864,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2980,7 +2980,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3252,7 +3252,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3822,7 +3822,7 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4018,7 +4018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6711d51cb46744dd8305293cc3fbc392aaff7a8f5095a7c4fae1e5113ef07c96" +"checksum compiler_builtins 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d7be038c8f003625c494e97c09bbcef65582b73f6aa86975f5273d8eba4c9d4c" "checksum compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "56c799b1f7142badf3b047b4c1f2074cc96b6b784fb2432f2ed9c87da0a03749" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" From d6add90c64a27de32a63b933f8f03d0c53fca4d0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 6 Mar 2019 15:01:30 +0100 Subject: [PATCH 23/30] Improve code --- src/tools/compiletest/src/runtest.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f7c02e831a9aa..7781ce74f411e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -291,7 +291,8 @@ impl<'test> TestCx<'test> { fn should_compile_successfully(&self) -> bool { match self.config.mode { CompileFail => self.props.compile_pass, - RunPass | JsDocTest => true, + RunPass => true, + JsDocTest => true, Ui => self.props.compile_pass, Incremental => { let revision = self.revision @@ -2728,6 +2729,8 @@ impl<'test> TestCx<'test> { if !res.status.success() { self.fatal_proc_rec("rustdoc-js test failed!", &res); } + } else { + self.fatal("no nodeJS"); } } From 00887f39d199bc63730d0dd19f8726451fdd5758 Mon Sep 17 00:00:00 2001 From: Wesley Norris Date: Mon, 4 Mar 2019 20:00:28 -0500 Subject: [PATCH 24/30] Adds diagnostic message and UI test. --- src/libsyntax/parse/parser.rs | 10 +++++++++- src/test/ui/issues/issue-56031.rs | 5 +++++ src/test/ui/issues/issue-56031.stderr | 10 ++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-56031.rs create mode 100644 src/test/ui/issues/issue-56031.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fd5038a8614f2..330be1133ca4b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6716,8 +6716,16 @@ impl<'a> Parser<'a> { ast::ImplPolarity::Positive }; + let possible_missing_trait = self.look_ahead(0, |t| t.is_keyword(keywords::For)); + // Parse both types and traits as a type, then reinterpret if necessary. - let ty_first = self.parse_ty()?; + let ty_first = self.parse_ty().map_err(|mut err| { + if possible_missing_trait { + err.help("did you forget a trait name after `impl`?"); + } + + err + })?; // If `for` is missing we try to recover. let has_for = self.eat_keyword(keywords::For); diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs new file mode 100644 index 0000000000000..7dbda3e46d13c --- /dev/null +++ b/src/test/ui/issues/issue-56031.rs @@ -0,0 +1,5 @@ +struct T; + +impl for T {} + +fn main() {} diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr new file mode 100644 index 0000000000000..dd4f95341ff22 --- /dev/null +++ b/src/test/ui/issues/issue-56031.stderr @@ -0,0 +1,10 @@ +error: expected `<`, found `T` + --> $DIR/issue-56031.rs:3:10 + | +LL | impl for T {} + | ^ expected `<` here + | + = help: did you forget a trait name after `impl`? + +error: aborting due to previous error + From e19b2289594746ce733588ac444df3fefaad4912 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 Mar 2019 23:18:03 +0300 Subject: [PATCH 25/30] Improve recovery for missing trait in a trait impl --- src/libsyntax/parse/parser.rs | 22 +++++++++++----------- src/test/ui/issues/issue-56031.rs | 1 + src/test/ui/issues/issue-56031.stderr | 8 +++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 330be1133ca4b..64f413e6dd8ee 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6716,16 +6716,16 @@ impl<'a> Parser<'a> { ast::ImplPolarity::Positive }; - let possible_missing_trait = self.look_ahead(0, |t| t.is_keyword(keywords::For)); - // Parse both types and traits as a type, then reinterpret if necessary. - let ty_first = self.parse_ty().map_err(|mut err| { - if possible_missing_trait { - err.help("did you forget a trait name after `impl`?"); - } - - err - })?; + let err_path = |span| ast::Path::from_ident(Ident::new(keywords::Invalid.name(), span)); + let ty_first = if self.token.is_keyword(keywords::For) && + self.look_ahead(1, |t| t != &token::Lt) { + let span = self.prev_span.between(self.span); + self.struct_span_err(span, "missing trait in a trait impl").emit(); + P(Ty { node: TyKind::Path(None, err_path(span)), span, id: ast::DUMMY_NODE_ID }) + } else { + self.parse_ty()? + }; // If `for` is missing we try to recover. let has_for = self.eat_keyword(keywords::For); @@ -6734,7 +6734,7 @@ impl<'a> Parser<'a> { let ty_second = if self.token == token::DotDot { // We need to report this error after `cfg` expansion for compatibility reasons self.bump(); // `..`, do not add it to expected tokens - Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID })) + Some(DummyResult::raw_ty(self.prev_span, true)) } else if has_for || self.token.can_begin_type() { Some(self.parse_ty()?) } else { @@ -6764,7 +6764,7 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) => path, _ => { self.span_err(ty_first.span, "expected a trait, found type"); - ast::Path::from_ident(Ident::new(keywords::Invalid.name(), ty_first.span)) + err_path(ty_first.span) } }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs index 7dbda3e46d13c..b68f56814678c 100644 --- a/src/test/ui/issues/issue-56031.rs +++ b/src/test/ui/issues/issue-56031.rs @@ -1,5 +1,6 @@ struct T; impl for T {} +//~^ ERROR missing trait in a trait impl fn main() {} diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr index dd4f95341ff22..3d7acee0a56eb 100644 --- a/src/test/ui/issues/issue-56031.stderr +++ b/src/test/ui/issues/issue-56031.stderr @@ -1,10 +1,8 @@ -error: expected `<`, found `T` - --> $DIR/issue-56031.rs:3:10 +error: missing trait in a trait impl + --> $DIR/issue-56031.rs:3:5 | LL | impl for T {} - | ^ expected `<` here - | - = help: did you forget a trait name after `impl`? + | ^ error: aborting due to previous error From 0a505a71d3b8d61e982b305caf6d39c227c05957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 2 Mar 2019 10:38:20 -0800 Subject: [PATCH 26/30] Parse lifetimes that start with a number and give specific error --- src/libsyntax/parse/lexer/mod.rs | 24 ++++++++++++++++------ src/test/ui/parser/numeric-lifetime.rs | 8 ++++++++ src/test/ui/parser/numeric-lifetime.stderr | 24 ++++++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/parser/numeric-lifetime.rs create mode 100644 src/test/ui/parser/numeric-lifetime.stderr diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index a7cde5fbb92cd..f45f5e65312c2 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1423,15 +1423,17 @@ impl<'a> StringReader<'a> { // If the character is an ident start not followed by another single // quote, then this is a lifetime name: - if ident_start(Some(c2)) && !self.ch_is('\'') { + if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') { while ident_continue(self.ch) { self.bump(); } // lifetimes shouldn't end with a single quote // if we find one, then this is an invalid character literal if self.ch_is('\'') { - self.err_span_(start_with_quote, self.next_pos, - "character literal may only contain one codepoint"); + self.err_span_( + start_with_quote, + self.next_pos, + "character literal may only contain one codepoint"); self.bump(); return Ok(token::Literal(token::Err(Symbol::intern("??")), None)) @@ -1444,6 +1446,16 @@ impl<'a> StringReader<'a> { self.mk_ident(&format!("'{}", lifetime_name)) }); + if c2.is_numeric() { + // this is a recovered lifetime written `'1`, error but accept it + self.err_span_( + start_with_quote, + self.pos, + "lifetimes can't start with a number", + ); + } + + return Ok(token::Lifetime(ident)); } @@ -1873,13 +1885,14 @@ fn is_block_doc_comment(s: &str) -> bool { res } +/// Determine whether `c` is a valid start for an ident. fn ident_start(c: Option) -> bool { let c = match c { Some(c) => c, None => return false, }; - (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c > '\x7f' && c.is_xid_start()) + (c.is_alphabetic() || c == '_' || (c > '\x7f' && c.is_xid_start())) } fn ident_continue(c: Option) -> bool { @@ -1888,8 +1901,7 @@ fn ident_continue(c: Option) -> bool { None => return false, }; - (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || - (c > '\x7f' && c.is_xid_continue()) + (c.is_alphabetic() || c.is_numeric() || c == '_' || (c > '\x7f' && c.is_xid_continue())) } #[inline] diff --git a/src/test/ui/parser/numeric-lifetime.rs b/src/test/ui/parser/numeric-lifetime.rs new file mode 100644 index 0000000000000..3483975a3cb8e --- /dev/null +++ b/src/test/ui/parser/numeric-lifetime.rs @@ -0,0 +1,8 @@ +struct S<'1> { s: &'1 usize } +//~^ ERROR lifetimes can't start with a number +//~| ERROR lifetimes can't start with a number +fn main() { + // verify that the parse error doesn't stop type checking + let x: usize = ""; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr new file mode 100644 index 0000000000000..1bbc508d57d4b --- /dev/null +++ b/src/test/ui/parser/numeric-lifetime.stderr @@ -0,0 +1,24 @@ +error: lifetimes can't start with a number + --> $DIR/numeric-lifetime.rs:1:10 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error: lifetimes can't start with a number + --> $DIR/numeric-lifetime.rs:1:20 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error[E0308]: mismatched types + --> $DIR/numeric-lifetime.rs:6:20 + | +LL | let x: usize = ""; + | ^^ expected usize, found reference + | + = note: expected type `usize` + found type `&'static str` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From a03e20db6d15fe1cdda64c0fbe934e36209a08f6 Mon Sep 17 00:00:00 2001 From: ishitatsuyuki Date: Thu, 31 Jan 2019 18:28:22 +0900 Subject: [PATCH 27/30] Fix fallout from #57667 --- src/libsyntax/ptr.rs | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index bc43630ae59b3..9afcb7c4621c9 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -29,7 +29,7 @@ use std::fmt::{self, Display, Debug}; use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; -use std::{mem, ptr, slice, vec}; +use std::{slice, vec}; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -66,45 +66,18 @@ impl P { pub fn map(mut self, f: F) -> P where F: FnOnce(T) -> T, { - let p: *mut T = &mut *self.ptr; + let x = f(*self.ptr); + *self.ptr = x; - // Leak self in case of panic. - // FIXME(eddyb) Use some sort of "free guard" that - // only deallocates, without dropping the pointee, - // in case the call the `f` below ends in a panic. - mem::forget(self); - - unsafe { - ptr::write(p, f(ptr::read(p))); - - // Recreate self from the raw pointer. - P { ptr: Box::from_raw(p) } - } + self } /// Optionally produce a new `P` from `self` without reallocating. pub fn filter_map(mut self, f: F) -> Option> where F: FnOnce(T) -> Option, { - let p: *mut T = &mut *self.ptr; - - // Leak self in case of panic. - // FIXME(eddyb) Use some sort of "free guard" that - // only deallocates, without dropping the pointee, - // in case the call the `f` below ends in a panic. - mem::forget(self); - - unsafe { - if let Some(v) = f(ptr::read(p)) { - ptr::write(p, v); - - // Recreate self from the raw pointer. - Some(P { ptr: Box::from_raw(p) }) - } else { - drop(Box::from_raw(p)); - None - } - } + *self.ptr = f(*self.ptr)?; + Some(self) } } From f690821d58650358f536606722a8f5531c8a6b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 8 Mar 2019 13:29:27 -0800 Subject: [PATCH 28/30] review comments --- src/libsyntax/parse/lexer/mod.rs | 8 ++++---- src/test/ui/parser/numeric-lifetime.rs | 4 ++-- src/test/ui/parser/numeric-lifetime.stderr | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index f45f5e65312c2..6d2256474a3df 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1451,11 +1451,10 @@ impl<'a> StringReader<'a> { self.err_span_( start_with_quote, self.pos, - "lifetimes can't start with a number", + "lifetimes cannot start with a number", ); } - return Ok(token::Lifetime(ident)); } @@ -1892,7 +1891,7 @@ fn ident_start(c: Option) -> bool { None => return false, }; - (c.is_alphabetic() || c == '_' || (c > '\x7f' && c.is_xid_start())) + (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c > '\x7f' && c.is_xid_start()) } fn ident_continue(c: Option) -> bool { @@ -1901,7 +1900,8 @@ fn ident_continue(c: Option) -> bool { None => return false, }; - (c.is_alphabetic() || c.is_numeric() || c == '_' || (c > '\x7f' && c.is_xid_continue())) + (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || + (c > '\x7f' && c.is_xid_continue()) } #[inline] diff --git a/src/test/ui/parser/numeric-lifetime.rs b/src/test/ui/parser/numeric-lifetime.rs index 3483975a3cb8e..2d82354c62cca 100644 --- a/src/test/ui/parser/numeric-lifetime.rs +++ b/src/test/ui/parser/numeric-lifetime.rs @@ -1,6 +1,6 @@ struct S<'1> { s: &'1 usize } -//~^ ERROR lifetimes can't start with a number -//~| ERROR lifetimes can't start with a number +//~^ ERROR lifetimes cannot start with a number +//~| ERROR lifetimes cannot start with a number fn main() { // verify that the parse error doesn't stop type checking let x: usize = ""; diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr index 1bbc508d57d4b..4018b24aac175 100644 --- a/src/test/ui/parser/numeric-lifetime.stderr +++ b/src/test/ui/parser/numeric-lifetime.stderr @@ -1,10 +1,10 @@ -error: lifetimes can't start with a number +error: lifetimes cannot start with a number --> $DIR/numeric-lifetime.rs:1:10 | LL | struct S<'1> { s: &'1 usize } | ^^ -error: lifetimes can't start with a number +error: lifetimes cannot start with a number --> $DIR/numeric-lifetime.rs:1:20 | LL | struct S<'1> { s: &'1 usize } From 3a83cb2c9ba2acca0577a5f4a092d7fc5b243faf Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Sat, 9 Mar 2019 03:39:23 +0000 Subject: [PATCH 29/30] Fix ICE in MIR pretty printing A `Def::Variant` should be considered as a function in mir pretty printing. Each variant has a constructor that we must print. Given the following enum definition: ``` pub enum TestMe { X(usize), } ``` We will need to generate a constructor for the variant `X` with a signature that looks something like the following: ``` fn TestMe::X(_1: usize) -> TestMe; ``` --- src/librustc_mir/util/pretty.rs | 4 +++- src/test/mir-opt/unusual-item-types.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index c3fbee3a2a6e5..af49f61ae86c7 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -1,4 +1,5 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def::CtorKind; use rustc::mir::*; use rustc::mir::visit::Visitor; use rustc::ty::{self, TyCtxt}; @@ -597,7 +598,8 @@ fn write_mir_sig( trace!("write_mir_sig: {:?}", src.instance); let descr = tcx.describe_def(src.def_id()); let is_function = match descr { - Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::StructCtor(..)) => true, + Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) | + Some(Def::StructCtor(_, CtorKind::Fn)) => true, _ => tcx.is_closure(src.def_id()), }; match (descr, src.promoted) { diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index fe85baa048e39..ced30381fda68 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -7,11 +7,18 @@ impl A { const ASSOCIATED_CONSTANT: i32 = 2; } +// See #59021 +enum Test { + X(usize), + Y { a: usize }, +} + enum E { V = 5, } fn main() { + let f = Test::X as fn(usize) -> Test; let v = Vec::::new(); } @@ -64,3 +71,14 @@ fn main() { // _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5]; // } // END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir + +// START rustc.Test-X.mir_map.0.mir +// fn Test::X(_1: usize) -> Test { +// let mut _0: Test; +// +// bb0: { +// _0 = Test::X(move _1,); +// return; +// } +// } +// END rustc.Test-X.mir_map.0.mir From df4ea90b39c808e858e05f3b4bb05fc29f812d26 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 9 Mar 2019 19:10:28 -0800 Subject: [PATCH 30/30] Use lifetime contravariance to elide more lifetimes in core+alloc+std --- src/liballoc/boxed.rs | 8 ++--- src/liballoc/rc.rs | 4 +-- src/liballoc/string.rs | 4 +-- src/liballoc/vec.rs | 16 +++++----- src/libcore/array.rs | 2 +- src/libcore/cmp.rs | 48 ++++++++++++++-------------- src/libcore/internal_macros.rs | 12 +++---- src/libcore/ptr.rs | 16 +++++----- src/libstd/collections/hash/set.rs | 8 ++--- src/libstd/error.rs | 8 ++--- src/libstd/ffi/c_str.rs | 12 +++---- src/libstd/ffi/os_str.rs | 16 +++++----- src/libstd/path.rs | 12 +++---- src/libstd/sys/cloudabi/shims/net.rs | 4 +-- src/libstd/sys/redox/net/mod.rs | 2 +- src/libstd/sys/sgx/net.rs | 4 +-- src/libstd/sys/unix/l4re.rs | 4 +-- src/libstd/sys/wasm/net.rs | 4 +-- src/libstd/sys_common/net.rs | 2 +- 19 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 74325a69e15ef..9bce142b483f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -489,7 +489,7 @@ impl From> for Pin> { } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { +impl From<&[T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// /// This conversion allocates on the heap @@ -503,7 +503,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { /// /// println!("{:?}", boxed_slice); /// ``` - fn from(slice: &'a [T]) -> Box<[T]> { + fn from(slice: &[T]) -> Box<[T]> { let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; boxed.copy_from_slice(slice); boxed @@ -511,7 +511,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl<'a> From<&'a str> for Box { +impl From<&str> for Box { /// Converts a `&str` into a `Box` /// /// This conversion allocates on the heap @@ -523,7 +523,7 @@ impl<'a> From<&'a str> for Box { /// println!("{}", boxed); /// ``` #[inline] - fn from(s: &'a str) -> Box { + fn from(s: &str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 12f75d84211e6..68eecd97ea11a 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1145,7 +1145,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> { +impl From<&[T]> for Rc<[T]> { #[inline] fn from(v: &[T]) -> Rc<[T]> { >::from_slice(v) @@ -1153,7 +1153,7 @@ impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> { } #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl<'a> From<&'a str> for Rc { +impl From<&str> for Rc { #[inline] fn from(v: &str) -> Rc { let rc = Rc::<[u8]>::from(v.as_bytes()); diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index b714df5d36b6a..a3e2098695f70 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2172,9 +2172,9 @@ impl AsRef<[u8]> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for String { +impl From<&str> for String { #[inline] - fn from(s: &'a str) -> String { + fn from(s: &str) -> String { s.to_owned() } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index adcd3d84f4832..cd62c3e05244c 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2182,25 +2182,25 @@ impl AsMut<[T]> for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Clone> From<&'a [T]> for Vec { +impl From<&[T]> for Vec { #[cfg(not(test))] - fn from(s: &'a [T]) -> Vec { + fn from(s: &[T]) -> Vec { s.to_vec() } #[cfg(test)] - fn from(s: &'a [T]) -> Vec { + fn from(s: &[T]) -> Vec { crate::slice::to_vec(s) } } #[stable(feature = "vec_from_mut", since = "1.19.0")] -impl<'a, T: Clone> From<&'a mut [T]> for Vec { +impl From<&mut [T]> for Vec { #[cfg(not(test))] - fn from(s: &'a mut [T]) -> Vec { + fn from(s: &mut [T]) -> Vec { s.to_vec() } #[cfg(test)] - fn from(s: &'a mut [T]) -> Vec { + fn from(s: &mut [T]) -> Vec { crate::slice::to_vec(s) } } @@ -2231,8 +2231,8 @@ impl From> for Box<[T]> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for Vec { - fn from(s: &'a str) -> Vec { +impl From<&str> for Vec { + fn from(s: &str) -> Vec { From::from(s.as_bytes()) } } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 9c6ecc4350246..dcd9ce6dad756 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -139,7 +139,7 @@ macro_rules! array_impls { } #[stable(feature = "try_from", since = "1.34.0")] - impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy { + impl TryFrom<&[T]> for [T; $N] where T: Copy { type Error = TryFromSliceError; fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> { diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 81fcdeee12d29..94bed3708369a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1004,26 +1004,26 @@ mod impls { // & pointers #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq { + impl PartialEq<&B> for &A where A: PartialEq { #[inline] - fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: & &B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: & &B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd { + impl PartialOrd<&B> for &A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'b B) -> Option { + fn partial_cmp(&self, other: &&B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: & &B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &A where A: Ord { @@ -1036,26 +1036,26 @@ mod impls { // &mut pointers #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { + impl PartialEq<&mut B> for &mut A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { + impl PartialOrd<&mut B> for &mut A where A: PartialOrd { #[inline] - fn partial_cmp(&self, other: &&'b mut B) -> Option { + fn partial_cmp(&self, other: &&mut B) -> Option { PartialOrd::partial_cmp(*self, *other) } #[inline] - fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) } + fn lt(&self, other: &&mut B) -> bool { PartialOrd::lt(*self, *other) } #[inline] - fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) } + fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) } + fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) } #[inline] - fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) } + fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &mut A where A: Ord { @@ -1066,18 +1066,18 @@ mod impls { impl Eq for &mut A where A: Eq {} #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq { + impl PartialEq<&mut B> for &A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq { + impl PartialEq<&B> for &mut A where A: PartialEq { #[inline] - fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) } + fn eq(&self, other: &&B) -> bool { PartialEq::eq(*self, *other) } #[inline] - fn ne(&self, other: &&'b B) -> bool { PartialEq::ne(*self, *other) } + fn ne(&self, other: &&B) -> bool { PartialEq::ne(*self, *other) } } } diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index faca785e488c3..b5c20582986b2 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -37,21 +37,21 @@ macro_rules! forward_ref_binop { } #[$attr] - impl<'a> $imp<&'a $u> for $t { + impl $imp<&$u> for $t { type Output = <$t as $imp<$u>>::Output; #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(self, *other) } } #[$attr] - impl<'a, 'b> $imp<&'a $u> for &'b $t { + impl $imp<&$u> for &$t { type Output = <$t as $imp<$u>>::Output; #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(*self, *other) } } @@ -67,9 +67,9 @@ macro_rules! forward_ref_op_assign { }; (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { #[$attr] - impl<'a> $imp<&'a $u> for $t { + impl $imp<&$u> for $t { #[inline] - fn $method(&mut self, other: &'a $u) { + fn $method(&mut self, other: &$u) { $imp::$method(self, *other); } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 53d4197603068..d288ca449dff3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2837,15 +2837,15 @@ impl fmt::Pointer for Unique { } #[unstable(feature = "ptr_internals", issue = "0")] -impl<'a, T: ?Sized> From<&'a mut T> for Unique { - fn from(reference: &'a mut T) -> Self { +impl From<&mut T> for Unique { + fn from(reference: &mut T) -> Self { unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } } } } #[unstable(feature = "ptr_internals", issue = "0")] -impl<'a, T: ?Sized> From<&'a T> for Unique { - fn from(reference: &'a T) -> Self { +impl From<&T> for Unique { + fn from(reference: &T) -> Self { unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } } } } @@ -3049,17 +3049,17 @@ impl From> for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl<'a, T: ?Sized> From<&'a mut T> for NonNull { +impl From<&mut T> for NonNull { #[inline] - fn from(reference: &'a mut T) -> Self { + fn from(reference: &mut T) -> Self { unsafe { NonNull { pointer: reference as *mut T } } } } #[stable(feature = "nonnull", since = "1.25.0")] -impl<'a, T: ?Sized> From<&'a T> for NonNull { +impl From<&T> for NonNull { #[inline] - fn from(reference: &'a T) -> Self { + fn from(reference: &T) -> Self { unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 8a599c11b2095..f2111f2d9e028 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -850,7 +850,7 @@ impl Default for HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet +impl BitOr<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -882,7 +882,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet +impl BitAnd<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -914,7 +914,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet +impl BitXor<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -946,7 +946,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> Sub<&'b HashSet> for &'a HashSet +impl Sub<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 2858308e8f8d5..3eb289501cb0f 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -337,7 +337,7 @@ impl From for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { +impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples @@ -351,13 +351,13 @@ impl<'a, 'b> From<&'b str> for Box { /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &'b str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&'a str> for Box { +impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// # Examples @@ -370,7 +370,7 @@ impl<'a> From<&'a str> for Box { /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &'a str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 139680e526fd6..ad3f45bfadaf4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -690,8 +690,8 @@ impl<'a> From> for CString { } #[stable(feature = "box_from_c_str", since = "1.17.0")] -impl<'a> From<&'a CStr> for Box { - fn from(s: &'a CStr) -> Box { +impl From<&CStr> for Box { + fn from(s: &CStr) -> Box { let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul()); unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } } @@ -767,7 +767,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a CStr> for Arc { +impl From<&CStr> for Arc { #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); @@ -789,7 +789,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a CStr> for Rc { +impl From<&CStr> for Rc { #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); @@ -1268,8 +1268,8 @@ impl ToOwned for CStr { } #[stable(feature = "cstring_asref", since = "1.7.0")] -impl<'a> From<&'a CStr> for CString { - fn from(s: &'a CStr) -> CString { +impl From<&CStr> for CString { + fn from(s: &CStr) -> CString { s.to_owned() } } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index f68eaeb9c7e1f..3a0590021c917 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -357,8 +357,8 @@ impl From for OsString { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized + AsRef> From<&'a T> for OsString { - fn from(s: &'a T) -> OsString { +impl> From<&T> for OsString { + fn from(s: &T) -> OsString { s.as_ref().to_os_string() } } @@ -421,8 +421,8 @@ impl PartialEq for str { } #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")] -impl<'a> PartialEq<&'a str> for OsString { - fn eq(&self, other: &&'a str) -> bool { +impl PartialEq<&str> for OsString { + fn eq(&self, other: &&str) -> bool { **self == **other } } @@ -656,8 +656,8 @@ impl OsStr { } #[stable(feature = "box_from_os_str", since = "1.17.0")] -impl<'a> From<&'a OsStr> for Box { - fn from(s: &'a OsStr) -> Box { +impl From<&OsStr> for Box { + fn from(s: &OsStr) -> Box { let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr; unsafe { Box::from_raw(rw) } } @@ -707,7 +707,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a OsStr> for Arc { +impl From<&OsStr> for Arc { #[inline] fn from(s: &OsStr) -> Arc { let arc = s.inner.into_arc(); @@ -729,7 +729,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a OsStr> for Rc { +impl From<&OsStr> for Rc { #[inline] fn from(s: &OsStr) -> Rc { let rc = s.inner.into_rc(); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 858a5778b8161..ea3fcd8ce2859 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1456,8 +1456,8 @@ impl PathBuf { } #[stable(feature = "box_from_path", since = "1.17.0")] -impl<'a> From<&'a Path> for Box { - fn from(path: &'a Path) -> Box { +impl From<&Path> for Box { + fn from(path: &Path) -> Box { let boxed: Box = path.inner.into(); let rw = Box::into_raw(boxed) as *mut Path; unsafe { Box::from_raw(rw) } @@ -1494,8 +1494,8 @@ impl Clone for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { - fn from(s: &'a T) -> PathBuf { +impl> From<&T> for PathBuf { + fn from(s: &T) -> PathBuf { PathBuf::from(s.as_ref().to_os_string()) } } @@ -1630,7 +1630,7 @@ impl From for Arc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a Path> for Arc { +impl From<&Path> for Arc { /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Arc { @@ -1650,7 +1650,7 @@ impl From for Rc { } #[stable(feature = "shared_from_slice2", since = "1.24.0")] -impl<'a> From<&'a Path> for Rc { +impl From<&Path> for Rc { /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. #[inline] fn from(s: &Path) -> Rc { diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs index 50d72dc7b240b..6d2a4962ab444 100644 --- a/src/libstd/sys/cloudabi/shims/net.rs +++ b/src/libstd/sys/cloudabi/shims/net.rs @@ -297,10 +297,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unsupported() } } diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index a172763f61313..dbaa140ed8a0f 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -35,7 +35,7 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; fn try_from(s: &str) -> io::Result { diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index ab8b2681393f8..e5e42e3d0b048 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -420,10 +420,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(v: &'a str) -> io::Result { + fn try_from(v: &str) -> io::Result { LookupHost::new(v.to_owned()) } } diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs index b6e8cc738946b..b9e725371a36e 100644 --- a/src/libstd/sys/unix/l4re.rs +++ b/src/libstd/sys/unix/l4re.rs @@ -447,10 +447,10 @@ pub mod net { unsafe impl Send for LookupHost {} - impl<'a> TryFrom<&'a str> for LookupHost { + impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unimpl!(); } } diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs index 1249832fb09d2..a2ea2dfbbc032 100644 --- a/src/libstd/sys/wasm/net.rs +++ b/src/libstd/sys/wasm/net.rs @@ -298,10 +298,10 @@ impl Iterator for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; - fn try_from(_v: &'a str) -> io::Result { + fn try_from(_v: &str) -> io::Result { unsupported() } } diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 36721171b1733..b9505aaa69ba5 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -157,7 +157,7 @@ impl Drop for LookupHost { } } -impl<'a> TryFrom<&'a str> for LookupHost { +impl TryFrom<&str> for LookupHost { type Error = io::Error; fn try_from(s: &str) -> io::Result {